chore: 再次排除敏感文件
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 19s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 19s
This commit is contained in:
parent
8ba754daad
commit
a16871fdc5
2
.gitignore
vendored
2
.gitignore
vendored
@ -36,3 +36,5 @@ coverage/
|
|||||||
.cache/
|
.cache/
|
||||||
tmp/
|
tmp/
|
||||||
temp/docs/credentials.md
|
temp/docs/credentials.md
|
||||||
|
docs/credentials.md
|
||||||
|
docs/AI回答.md
|
||||||
|
|||||||
885
docs/AI回答.md
885
docs/AI回答.md
@ -1,885 +0,0 @@
|
|||||||
([Files][1])([Files][2])([Files][3])([Files][4])([Files][5])
|
|
||||||
|
|
||||||
可以。下面我把 **知习后端 Redis 设计** 单独整理一版。
|
|
||||||
|
|
||||||
你可以把它理解成:
|
|
||||||
|
|
||||||
```text
|
|
||||||
MySQL:长期真实数据,必须可靠保存
|
|
||||||
Redis:短期状态、缓存、队列、限流、锁、任务进度
|
|
||||||
```
|
|
||||||
|
|
||||||
Redis **不需要建表**,需要设计的是:
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. Redis 用在哪些场景
|
|
||||||
2. Key 怎么命名
|
|
||||||
3. Value 存什么
|
|
||||||
4. 过期时间多久
|
|
||||||
5. 哪些数据绝对不能只放 Redis
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 一、Redis 在知习里的定位
|
|
||||||
|
|
||||||
Redis 不作为主数据库。
|
|
||||||
|
|
||||||
它主要负责:
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. 缓存
|
|
||||||
2. 限流
|
|
||||||
3. 队列
|
|
||||||
4. 临时任务状态
|
|
||||||
5. 分布式锁
|
|
||||||
6. 防重复提交
|
|
||||||
7. AI 调用次数统计
|
|
||||||
8. 短期 token / 黑名单
|
|
||||||
9. 通知任务调度
|
|
||||||
```
|
|
||||||
|
|
||||||
核心业务数据仍然必须写入 MySQL:
|
|
||||||
|
|
||||||
```text
|
|
||||||
用户
|
|
||||||
知识库
|
|
||||||
知识点
|
|
||||||
学习记录
|
|
||||||
主动回忆回答
|
|
||||||
AI 分析结果
|
|
||||||
待巩固项
|
|
||||||
复习计划
|
|
||||||
学习活跃记录
|
|
||||||
通知记录
|
|
||||||
用户设置
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 二、Redis Key 命名规范
|
|
||||||
|
|
||||||
建议统一用这种格式:
|
|
||||||
|
|
||||||
```text
|
|
||||||
业务域:对象类型:对象ID:字段
|
|
||||||
```
|
|
||||||
|
|
||||||
例如:
|
|
||||||
|
|
||||||
```text
|
|
||||||
cache:user:123:profile
|
|
||||||
rate:user:123:ai:daily:2026-05-09
|
|
||||||
lock:ai-analysis:session:987
|
|
||||||
job:ai-analysis:abc123:status
|
|
||||||
```
|
|
||||||
|
|
||||||
统一规则:
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. 全部小写
|
|
||||||
2. 用冒号 : 分隔
|
|
||||||
3. 从大范围到小范围
|
|
||||||
4. userId、jobId、sessionId 明确写在 key 里
|
|
||||||
5. 带日期的 key 用 YYYY-MM-DD
|
|
||||||
6. 所有临时 key 必须设置 TTL
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 三、Redis 主要使用场景
|
|
||||||
|
|
||||||
## 1. 缓存 Cache
|
|
||||||
|
|
||||||
用于缓存高频读取的数据,减少 MySQL 压力。
|
|
||||||
|
|
||||||
### 用户资料缓存
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
cache:user:{userId}:profile
|
|
||||||
|
|
||||||
value:
|
|
||||||
{
|
|
||||||
"id": 123,
|
|
||||||
"nickname": "李明",
|
|
||||||
"avatarUrl": null,
|
|
||||||
"learningIdentity": "系统学习者",
|
|
||||||
"learningDirection": "认知科学"
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
5-10 分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
### 用户知识库列表缓存
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
cache:user:{userId}:knowledge-bases
|
|
||||||
|
|
||||||
value:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"title": "认知心理学",
|
|
||||||
"itemCount": 42
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
3-5 分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
### 当前用户设置缓存
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
cache:user:{userId}:preferences
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
10 分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:
|
|
||||||
|
|
||||||
```text
|
|
||||||
缓存可以丢
|
|
||||||
MySQL 不能丢
|
|
||||||
缓存更新不及时也没关系,但关键业务查询必须以 MySQL 为准
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 限流 Rate Limit
|
|
||||||
|
|
||||||
用于控制请求频率和 AI 成本。
|
|
||||||
|
|
||||||
### 用户每日 AI 调用次数
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
rate:user:{userId}:ai:daily:{date}
|
|
||||||
|
|
||||||
example:
|
|
||||||
rate:user:123:ai:daily:2026-05-09
|
|
||||||
|
|
||||||
value:
|
|
||||||
8
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
到当天结束,或者 24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
用途:
|
|
||||||
|
|
||||||
```text
|
|
||||||
限制每天 AI 分析次数
|
|
||||||
限制生成回忆测试次数
|
|
||||||
限制找薄弱知识点次数
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### IP 请求频率限制
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
rate:ip:{ip}:request:{minute}
|
|
||||||
|
|
||||||
example:
|
|
||||||
rate:ip:1.2.3.4:request:2026-05-09T10:35
|
|
||||||
|
|
||||||
value:
|
|
||||||
42
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
60-120 秒
|
|
||||||
```
|
|
||||||
|
|
||||||
用途:
|
|
||||||
|
|
||||||
```text
|
|
||||||
防刷接口
|
|
||||||
防反馈表单乱提交
|
|
||||||
防登录接口暴力请求
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 登录尝试次数
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
rate:login:{ip}:{date}
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
10-30 分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
Apple 登录一般问题不大,但后面如果有邮箱登录、验证码登录,这个会用到。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 分布式锁 Lock
|
|
||||||
|
|
||||||
用于防止重复提交。
|
|
||||||
|
|
||||||
### 防止重复 AI 分析
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
lock:ai-analysis:session:{sessionId}
|
|
||||||
|
|
||||||
example:
|
|
||||||
lock:ai-analysis:session:987
|
|
||||||
|
|
||||||
value:
|
|
||||||
randomToken
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
60-300 秒
|
|
||||||
```
|
|
||||||
|
|
||||||
场景:
|
|
||||||
|
|
||||||
```text
|
|
||||||
用户连续点两次“提交 AI 分析”
|
|
||||||
后端只允许创建一个分析任务
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 防止重复导入资料
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
lock:document-import:{importId}
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
5-30 分钟
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 防止重复生成复习计划
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
lock:review-plan:user:{userId}:item:{itemId}
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
60-300 秒
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:
|
|
||||||
|
|
||||||
```text
|
|
||||||
锁一定要设置 TTL
|
|
||||||
解锁时要校验 value,不能误删别人的锁
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. AI 分析任务状态
|
|
||||||
|
|
||||||
AI 分析建议用异步任务。
|
|
||||||
|
|
||||||
流程:
|
|
||||||
|
|
||||||
```text
|
|
||||||
App 提交回答
|
|
||||||
→ 后端创建 ai_analysis_jobs 记录
|
|
||||||
→ 加入 Redis 队列
|
|
||||||
→ 返回 jobId
|
|
||||||
→ Worker 调用 AI
|
|
||||||
→ 结果写入 MySQL
|
|
||||||
→ Redis 状态改为 completed
|
|
||||||
```
|
|
||||||
|
|
||||||
### 任务状态 key
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:ai-analysis:{jobId}:status
|
|
||||||
|
|
||||||
value:
|
|
||||||
pending / processing / completed / failed
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
### 任务进度 key
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:ai-analysis:{jobId}:progress
|
|
||||||
|
|
||||||
value:
|
|
||||||
0-100
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
### 任务错误信息
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:ai-analysis:{jobId}:error
|
|
||||||
|
|
||||||
value:
|
|
||||||
"AI provider timeout"
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Redis 只存临时状态
|
|
||||||
最终任务记录和分析结果必须写入 MySQL:
|
|
||||||
ai_analysis_jobs
|
|
||||||
ai_analysis_results
|
|
||||||
focus_items
|
|
||||||
review_cards
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 资料导入任务状态
|
|
||||||
|
|
||||||
导入资料也建议异步。
|
|
||||||
|
|
||||||
场景:
|
|
||||||
|
|
||||||
```text
|
|
||||||
上传 PDF
|
|
||||||
粘贴长文本
|
|
||||||
导入链接
|
|
||||||
AI 解析生成知识点
|
|
||||||
```
|
|
||||||
|
|
||||||
### 导入任务状态
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:document-import:{importId}:status
|
|
||||||
|
|
||||||
value:
|
|
||||||
pending / parsing / chunking / generating / completed / failed
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
### 导入进度
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:document-import:{importId}:progress
|
|
||||||
|
|
||||||
value:
|
|
||||||
0-100
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
### 导入处理中提示
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
job:document-import:{importId}:message
|
|
||||||
|
|
||||||
value:
|
|
||||||
"正在提取关键知识点"
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
最终结果写入 MySQL:
|
|
||||||
|
|
||||||
```text
|
|
||||||
document_imports
|
|
||||||
uploaded_files
|
|
||||||
knowledge_items
|
|
||||||
knowledge_item_relations
|
|
||||||
tags
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. BullMQ 队列
|
|
||||||
|
|
||||||
如果后端是 Node.js / NestJS,建议用 BullMQ。
|
|
||||||
|
|
||||||
队列由 BullMQ 自动管理 Redis key,不需要你自己建。
|
|
||||||
|
|
||||||
建议预留 3 个队列:
|
|
||||||
|
|
||||||
```text
|
|
||||||
ai-analysis
|
|
||||||
document-import
|
|
||||||
notification
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ai-analysis 队列
|
|
||||||
|
|
||||||
任务数据:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"jobId": 123,
|
|
||||||
"userId": 456,
|
|
||||||
"sessionId": 789,
|
|
||||||
"answerId": 1001,
|
|
||||||
"jobType": "active_recall_analysis"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
处理逻辑:
|
|
||||||
|
|
||||||
```text
|
|
||||||
读取用户回答
|
|
||||||
调用 AI
|
|
||||||
生成分析结果
|
|
||||||
写入 ai_analysis_results
|
|
||||||
生成 focus_items
|
|
||||||
生成 review_cards
|
|
||||||
发送通知
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### document-import 队列
|
|
||||||
|
|
||||||
任务数据:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"importId": 123,
|
|
||||||
"userId": 456,
|
|
||||||
"knowledgeBaseId": 789,
|
|
||||||
"sourceType": "file"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
处理逻辑:
|
|
||||||
|
|
||||||
```text
|
|
||||||
解析文件
|
|
||||||
提取文本
|
|
||||||
分段
|
|
||||||
生成知识点
|
|
||||||
写入 knowledge_items
|
|
||||||
更新 document_imports 状态
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### notification 队列
|
|
||||||
|
|
||||||
任务数据:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"userId": 456,
|
|
||||||
"type": "review_due",
|
|
||||||
"title": "8 张卡片今日到期复习",
|
|
||||||
"data": {
|
|
||||||
"reviewCount": 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
处理逻辑:
|
|
||||||
|
|
||||||
```text
|
|
||||||
写入 notifications 表
|
|
||||||
后面可扩展推送 APNs
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 四、Redis Key 总表
|
|
||||||
|
|
||||||
## 缓存类
|
|
||||||
|
|
||||||
```text
|
|
||||||
cache:user:{userId}:profile
|
|
||||||
cache:user:{userId}:preferences
|
|
||||||
cache:user:{userId}:knowledge-bases
|
|
||||||
cache:knowledge-base:{knowledgeBaseId}:summary
|
|
||||||
cache:review:user:{userId}:due-count
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 限流类
|
|
||||||
|
|
||||||
```text
|
|
||||||
rate:user:{userId}:ai:daily:{date}
|
|
||||||
rate:user:{userId}:feedback:hourly
|
|
||||||
rate:ip:{ip}:request:{minute}
|
|
||||||
rate:ip:{ip}:login:{date}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 锁类
|
|
||||||
|
|
||||||
```text
|
|
||||||
lock:ai-analysis:session:{sessionId}
|
|
||||||
lock:ai-analysis:answer:{answerId}
|
|
||||||
lock:document-import:{importId}
|
|
||||||
lock:review-plan:user:{userId}:item:{itemId}
|
|
||||||
lock:feedback:ip:{ip}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 任务状态类
|
|
||||||
|
|
||||||
```text
|
|
||||||
job:ai-analysis:{jobId}:status
|
|
||||||
job:ai-analysis:{jobId}:progress
|
|
||||||
job:ai-analysis:{jobId}:error
|
|
||||||
|
|
||||||
job:document-import:{importId}:status
|
|
||||||
job:document-import:{importId}:progress
|
|
||||||
job:document-import:{importId}:message
|
|
||||||
job:document-import:{importId}:error
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 会话临时状态
|
|
||||||
|
|
||||||
```text
|
|
||||||
session:learning:{sessionId}:heartbeat
|
|
||||||
session:learning:{sessionId}:current-step
|
|
||||||
session:active-recall:{sessionId}:draft
|
|
||||||
```
|
|
||||||
|
|
||||||
例如用户正在写回答,可以短期保存草稿:
|
|
||||||
|
|
||||||
```text
|
|
||||||
key:
|
|
||||||
session:active-recall:{sessionId}:draft
|
|
||||||
|
|
||||||
ttl:
|
|
||||||
1-24 小时
|
|
||||||
```
|
|
||||||
|
|
||||||
最终提交后还是写 MySQL。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Token / 黑名单
|
|
||||||
|
|
||||||
```text
|
|
||||||
auth:refresh-token:blacklist:{tokenId}
|
|
||||||
auth:access-token:blacklist:{jwtId}
|
|
||||||
```
|
|
||||||
|
|
||||||
退出登录或注销账号时可用。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 五、TTL 建议
|
|
||||||
|
|
||||||
```text
|
|
||||||
用户资料缓存:5-10 分钟
|
|
||||||
知识库列表缓存:3-5 分钟
|
|
||||||
AI 每日限流:到当天结束或 24 小时
|
|
||||||
IP 请求限流:60-120 秒
|
|
||||||
登录尝试限流:10-30 分钟
|
|
||||||
AI 分析任务状态:24 小时
|
|
||||||
资料导入任务状态:24 小时
|
|
||||||
分布式锁:60 秒到 30 分钟,按任务类型决定
|
|
||||||
学习草稿:1-24 小时
|
|
||||||
Token 黑名单:到 token 原本过期时间
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 六、Redis 数据类型建议
|
|
||||||
|
|
||||||
## String
|
|
||||||
|
|
||||||
最常用。
|
|
||||||
|
|
||||||
用于:
|
|
||||||
|
|
||||||
```text
|
|
||||||
缓存 JSON
|
|
||||||
计数器
|
|
||||||
状态
|
|
||||||
锁
|
|
||||||
```
|
|
||||||
|
|
||||||
示例:
|
|
||||||
|
|
||||||
```text
|
|
||||||
rate:user:123:ai:daily:2026-05-09 = 8
|
|
||||||
job:ai-analysis:1001:status = processing
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Hash
|
|
||||||
|
|
||||||
可选,用于对象字段更新频繁的场景。
|
|
||||||
|
|
||||||
例如:
|
|
||||||
|
|
||||||
```text
|
|
||||||
job:ai-analysis:1001
|
|
||||||
status = processing
|
|
||||||
progress = 40
|
|
||||||
message = 正在分析薄弱点
|
|
||||||
```
|
|
||||||
|
|
||||||
v0.1 也可以先用 String 多 key,简单直接。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## List / Stream
|
|
||||||
|
|
||||||
队列相关,但如果使用 BullMQ,不需要自己操作。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Set
|
|
||||||
|
|
||||||
可选。
|
|
||||||
|
|
||||||
比如记录某天处理过的学习项:
|
|
||||||
|
|
||||||
```text
|
|
||||||
set:user:{userId}:reviewed-items:{date}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sorted Set
|
|
||||||
|
|
||||||
后期可用于按时间排序的任务。
|
|
||||||
|
|
||||||
例如:
|
|
||||||
|
|
||||||
```text
|
|
||||||
zset:review:due
|
|
||||||
```
|
|
||||||
|
|
||||||
但 v0.1 可以先不做,复习到期直接查 MySQL。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 七、哪些不要放 Redis
|
|
||||||
|
|
||||||
不要把这些只放 Redis:
|
|
||||||
|
|
||||||
```text
|
|
||||||
用户资料
|
|
||||||
知识库内容
|
|
||||||
知识点内容
|
|
||||||
学习记录
|
|
||||||
主动回忆回答
|
|
||||||
AI 分析结果
|
|
||||||
待巩固项
|
|
||||||
复习卡片
|
|
||||||
复习记录
|
|
||||||
学习活跃记录
|
|
||||||
通知记录
|
|
||||||
用户设置
|
|
||||||
协议同意记录
|
|
||||||
```
|
|
||||||
|
|
||||||
这些全部要写 MySQL。
|
|
||||||
|
|
||||||
Redis 可以缓存它们,但不是唯一来源。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 八、Redis 和 MySQL 的典型组合流程
|
|
||||||
|
|
||||||
## AI 分析流程
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. MySQL 创建 ai_analysis_jobs
|
|
||||||
2. Redis 加入 ai-analysis 队列
|
|
||||||
3. Redis 存 job 状态 processing
|
|
||||||
4. Worker 调用 AI
|
|
||||||
5. MySQL 写 ai_analysis_results
|
|
||||||
6. MySQL 写 focus_items
|
|
||||||
7. MySQL 写 review_cards
|
|
||||||
8. Redis 存 job 状态 completed
|
|
||||||
9. MySQL 写 notifications
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 资料导入流程
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. MySQL 创建 document_imports
|
|
||||||
2. Redis 加入 document-import 队列
|
|
||||||
3. Redis 存导入进度
|
|
||||||
4. Worker 解析文件
|
|
||||||
5. MySQL 写 knowledge_items
|
|
||||||
6. MySQL 更新 document_imports 为 success
|
|
||||||
7. Redis 状态 completed
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 学习活跃图流程
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. 用户完成学习动作
|
|
||||||
2. MySQL 写 learning_records
|
|
||||||
3. MySQL 更新 daily_learning_activities
|
|
||||||
4. Redis 可短期缓存今日活跃统计
|
|
||||||
5. App 查询活跃图时优先查 MySQL,必要时加缓存
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 九、v0.1 Redis 最小落地范围
|
|
||||||
|
|
||||||
第一版不用把所有 Redis 场景都做完。
|
|
||||||
|
|
||||||
建议先做:
|
|
||||||
|
|
||||||
```text
|
|
||||||
1. Redis 连接
|
|
||||||
2. /health 检查 Redis
|
|
||||||
3. RedisService
|
|
||||||
4. AI 每日调用限流
|
|
||||||
5. AI 分析队列
|
|
||||||
6. AI 分析任务状态
|
|
||||||
7. 防重复提交锁
|
|
||||||
8. document-import 队列预留
|
|
||||||
9. notification 队列预留
|
|
||||||
```
|
|
||||||
|
|
||||||
暂时不做:
|
|
||||||
|
|
||||||
```text
|
|
||||||
复杂缓存策略
|
|
||||||
Sorted Set 复习调度
|
|
||||||
复杂分布式任务调度
|
|
||||||
全量通知推送
|
|
||||||
复杂排行榜
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 十、给 Trae 的提示词
|
|
||||||
|
|
||||||
```text
|
|
||||||
请为「知习」api-server 设计并接入 Redis。
|
|
||||||
|
|
||||||
注意:
|
|
||||||
Redis 不需要像 MySQL 一样建表。
|
|
||||||
Redis 只用于缓存、限流、队列、临时状态、分布式锁、防重复提交和任务进度。
|
|
||||||
核心业务数据必须写入 MySQL,不能只存在 Redis。
|
|
||||||
|
|
||||||
请完成以下内容:
|
|
||||||
|
|
||||||
1. 基础接入
|
|
||||||
- docker-compose 增加 redis:7-alpine
|
|
||||||
- 增加 RedisModule
|
|
||||||
- 增加 RedisService
|
|
||||||
- 支持 REDIS_HOST、REDIS_PORT、REDIS_PASSWORD、REDIS_DB、REDIS_URL
|
|
||||||
- /health 检查 Redis 是否可用
|
|
||||||
|
|
||||||
2. RedisService 方法
|
|
||||||
- get
|
|
||||||
- set
|
|
||||||
- del
|
|
||||||
- exists
|
|
||||||
- expire
|
|
||||||
- ttl
|
|
||||||
- incr
|
|
||||||
- setNx
|
|
||||||
- lock
|
|
||||||
- unlock
|
|
||||||
|
|
||||||
3. Key 命名规范
|
|
||||||
请创建文档 docs/redis-key-design.md,包含以下 key 规范:
|
|
||||||
|
|
||||||
缓存:
|
|
||||||
cache:user:{userId}:profile
|
|
||||||
cache:user:{userId}:preferences
|
|
||||||
cache:user:{userId}:knowledge-bases
|
|
||||||
|
|
||||||
限流:
|
|
||||||
rate:user:{userId}:ai:daily:{date}
|
|
||||||
rate:ip:{ip}:request:{minute}
|
|
||||||
rate:user:{userId}:feedback:hourly
|
|
||||||
|
|
||||||
锁:
|
|
||||||
lock:ai-analysis:session:{sessionId}
|
|
||||||
lock:ai-analysis:answer:{answerId}
|
|
||||||
lock:document-import:{importId}
|
|
||||||
lock:review-plan:user:{userId}:item:{itemId}
|
|
||||||
|
|
||||||
任务状态:
|
|
||||||
job:ai-analysis:{jobId}:status
|
|
||||||
job:ai-analysis:{jobId}:progress
|
|
||||||
job:ai-analysis:{jobId}:error
|
|
||||||
job:document-import:{importId}:status
|
|
||||||
job:document-import:{importId}:progress
|
|
||||||
job:document-import:{importId}:message
|
|
||||||
job:document-import:{importId}:error
|
|
||||||
|
|
||||||
4. BullMQ 队列
|
|
||||||
请预留以下队列:
|
|
||||||
- ai-analysis
|
|
||||||
- document-import
|
|
||||||
- notification
|
|
||||||
|
|
||||||
5. AI 分析任务
|
|
||||||
请实现基础队列结构:
|
|
||||||
- 创建 AI 分析任务时写入 MySQL ai_analysis_jobs
|
|
||||||
- 添加任务到 Redis BullMQ 队列
|
|
||||||
- Redis 记录任务 status/progress
|
|
||||||
- Worker 处理完成后更新 MySQL
|
|
||||||
- Redis 更新状态为 completed
|
|
||||||
|
|
||||||
6. 限流
|
|
||||||
请实现基础 AI 调用限流:
|
|
||||||
rate:user:{userId}:ai:daily:{date}
|
|
||||||
用于限制用户每日 AI 分析调用次数。
|
|
||||||
|
|
||||||
7. 分布式锁
|
|
||||||
请实现 lock/unlock 工具,防止重复提交 AI 分析任务。
|
|
||||||
锁必须有 TTL。
|
|
||||||
解锁时要校验 token,不能误删其他请求的锁。
|
|
||||||
|
|
||||||
8. 注意事项
|
|
||||||
- 不要把用户、知识库、学习记录、AI 分析结果、待巩固项、复习计划只存 Redis
|
|
||||||
- Redis 中所有临时状态必须设置 TTL
|
|
||||||
- BullMQ 自动创建的 Redis key 不需要手动管理
|
|
||||||
- 代码要模块化,方便后续扩展
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
一句话总结:
|
|
||||||
|
|
||||||
**Redis 在知习里不是“另一个 MySQL”,它是系统的加速器和调度器。MySQL 存结果,Redis 管过程。**
|
|
||||||
|
|
||||||
[1]: file://my_files/file_00000000e760722fbb391fe031a23b24 "personal_developer_startup_plan.md"
|
|
||||||
[2]: file://my_files/file_00000000cbe0722fb8f20caa41630738 "Pasted text.txt"
|
|
||||||
[3]: file://my_files/file_0000000013c071fdbc2b510f32da8546 "Pasted text.txt"
|
|
||||||
[4]: file://my_files/file_00000000ffd071fd9492b93fd9ebf5ba "Pasted text.txt"
|
|
||||||
[5]: file://my_files/file_0000000061e471f590475885fd76860c "REAL_MIGRATION_STATUS.md"
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
# 知习 (zhixi) 凭据与配置
|
|
||||||
|
|
||||||
> ⚠️ 本文件包含敏感信息,**不要提交到公开仓库**。
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## 服务器
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| ------ | ------------------ |
|
|
||||||
| IP | 81.70.187.179 |
|
|
||||||
| SSH 用户 | ubuntu |
|
|
||||||
| SSH 密钥 | `服务器密钥/WangDL.pem` |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## MySQL
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| ------- | ---------------------------------------------------------- |
|
|
||||||
| Host | 127.0.0.1:3306(服务器内部)/ 通过 SSH 隧道 localhost:3306 |
|
|
||||||
| 数据库名 | zhixi |
|
|
||||||
| root 密码 | `Zhixi@2026!Root` |
|
|
||||||
| 业务账号 | `zhixi_user` |
|
|
||||||
| 业务密码 | `Zhixi@2026!App` |
|
|
||||||
| 连接字符串 | `mysql://zhixi_user:Zhixi@2026!App@mysql-zhixi:3306/zhixi` |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## Redis
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| ---- | ----------------------------------------------- |
|
|
||||||
| Host | 127.0.0.1:6379(服务器内部)/ 通过 SSH 隧道 localhost:6379 |
|
|
||||||
| 密码 | `Rds@nTsgKrcqAkbuf6PwJIFMZQzF` |
|
|
||||||
| 最大内存 | 256MB |
|
|
||||||
| 淘汰策略 | allkeys-lru |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## JWT
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| --------------- | ------------------------------------------------------------------ |
|
|
||||||
| Secret | `98b1e7e377a40021ad7c46c55e467d2a218a89db7afc7c912780152ad64bdc45` |
|
|
||||||
| accessToken 过期 | 1h |
|
|
||||||
| refreshToken 过期 | 7d |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## Swagger API 文档
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| ---- | ------------------------------------ |
|
|
||||||
| URL | <http://81.70.187.179:3001/api-docs> |
|
|
||||||
| 用户名 | `admin` |
|
|
||||||
| 密码 | `Swgr@fmDentAYVXQUpG6oZDpJ` |
|
|
||||||
| 认证方式 | Basic Auth |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## Gitea
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
|
||||||
| ------------ | ------------------------------------------ |
|
|
||||||
| URL | <http://81.70.187.179:3000> |
|
|
||||||
| SSH | ssh://git\@81.70.187.179:2222 |
|
|
||||||
| Runner Token | `9ypD3K9SWXR17CUNbWsvBxMIfz0MBqLiBLcRkGRZ` |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## 端口映射
|
|
||||||
|
|
||||||
| 端口 | 服务 |
|
|
||||||
| ---- | ------------------------------ |
|
|
||||||
| 22 | SSH |
|
|
||||||
| 3000 | Gitea |
|
|
||||||
| 3001 | zhixi-api |
|
|
||||||
| 3306 | MySQL(仅 127.0.0.1,通过 SSH 隧道访问) |
|
|
||||||
| 6379 | Redis(仅 127.0.0.1,通过 SSH 隧道访问) |
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## SSH 隧道(本地开发用)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -f -N -L 3306:127.0.0.1:3306 -L 6379:127.0.0.1:6379 \
|
|
||||||
-i api-server/服务器密钥/WangDL.pem ubuntu@81.70.187.179
|
|
||||||
```
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## 本地环境变量(.env)
|
|
||||||
|
|
||||||
```env
|
|
||||||
PORT=3000
|
|
||||||
NODE_ENV=development
|
|
||||||
DATABASE_URL="mysql://zhixi_user:Zhixi@2026!App@localhost:3306/zhixi"
|
|
||||||
REDIS_HOST=localhost
|
|
||||||
REDIS_PORT=6379
|
|
||||||
REDIS_PASSWORD=Rds@nTsgKrcqAkbuf6PwJIFMZQzF
|
|
||||||
JWT_SECRET=98b1e7e377a40021ad7c46c55e467d2a218a89db7afc7c912780152ad64bdc45
|
|
||||||
AI_PROVIDER=mock
|
|
||||||
ENABLE_SWAGGER=true
|
|
||||||
SWAGGER_USER=admin
|
|
||||||
SWAGGER_PASSWORD=Swgr@fmDentAYVXQUpG6oZDpJ
|
|
||||||
```
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user