api-server/docs/AI回答.md
WangDL 8ba754daad
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 2m1s
ci: 改用 host 模式 runner + 纯 shell workflow
2026-05-09 21:05:03 +08:00

886 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

([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"