api-server/docs/AI回答.md
WangDL 4435e4a8ab
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 11s
docs: 补移 AI回答.md 到 docs/
2026-05-09 20:33:33 +08:00

13 KiB
Raw Blame History

(Files)(Files)(Files)(Files)(Files)

可以。下面我把 知习后端 Redis 设计 单独整理一版。

你可以把它理解成:

MySQL长期真实数据必须可靠保存
Redis短期状态、缓存、队列、限流、锁、任务进度

Redis 不需要建表,需要设计的是:

1. Redis 用在哪些场景
2. Key 怎么命名
3. Value 存什么
4. 过期时间多久
5. 哪些数据绝对不能只放 Redis

一、Redis 在知习里的定位

Redis 不作为主数据库。

它主要负责:

1. 缓存
2. 限流
3. 队列
4. 临时任务状态
5. 分布式锁
6. 防重复提交
7. AI 调用次数统计
8. 短期 token / 黑名单
9. 通知任务调度

核心业务数据仍然必须写入 MySQL

用户
知识库
知识点
学习记录
主动回忆回答
AI 分析结果
待巩固项
复习计划
学习活跃记录
通知记录
用户设置

二、Redis Key 命名规范

建议统一用这种格式:

业务域:对象类型:对象ID:字段

例如:

cache:user:123:profile
rate:user:123:ai:daily:2026-05-09
lock:ai-analysis:session:987
job:ai-analysis:abc123:status

统一规则:

1. 全部小写
2. 用冒号 : 分隔
3. 从大范围到小范围
4. userId、jobId、sessionId 明确写在 key 里
5. 带日期的 key 用 YYYY-MM-DD
6. 所有临时 key 必须设置 TTL

三、Redis 主要使用场景

1. 缓存 Cache

用于缓存高频读取的数据,减少 MySQL 压力。

用户资料缓存

key:
cache:user:{userId}:profile

value:
{
  "id": 123,
  "nickname": "李明",
  "avatarUrl": null,
  "learningIdentity": "系统学习者",
  "learningDirection": "认知科学"
}

ttl:
5-10 分钟

用户知识库列表缓存

key:
cache:user:{userId}:knowledge-bases

value:
[
  {
    "id": 1,
    "title": "认知心理学",
    "itemCount": 42
  }
]

ttl:
3-5 分钟

当前用户设置缓存

key:
cache:user:{userId}:preferences

ttl:
10 分钟

注意:

缓存可以丢
MySQL 不能丢
缓存更新不及时也没关系,但关键业务查询必须以 MySQL 为准

2. 限流 Rate Limit

用于控制请求频率和 AI 成本。

用户每日 AI 调用次数

key:
rate:user:{userId}:ai:daily:{date}

example:
rate:user:123:ai:daily:2026-05-09

value:
8

ttl:
到当天结束,或者 24 小时

用途:

限制每天 AI 分析次数
限制生成回忆测试次数
限制找薄弱知识点次数

IP 请求频率限制

key:
rate:ip:{ip}:request:{minute}

example:
rate:ip:1.2.3.4:request:2026-05-09T10:35

value:
42

ttl:
60-120 秒

用途:

防刷接口
防反馈表单乱提交
防登录接口暴力请求

登录尝试次数

key:
rate:login:{ip}:{date}

ttl:
10-30 分钟

Apple 登录一般问题不大,但后面如果有邮箱登录、验证码登录,这个会用到。


3. 分布式锁 Lock

用于防止重复提交。

防止重复 AI 分析

key:
lock:ai-analysis:session:{sessionId}

example:
lock:ai-analysis:session:987

value:
randomToken

ttl:
60-300 秒

场景:

用户连续点两次“提交 AI 分析”
后端只允许创建一个分析任务

防止重复导入资料

key:
lock:document-import:{importId}

ttl:
5-30 分钟

防止重复生成复习计划

key:
lock:review-plan:user:{userId}:item:{itemId}

ttl:
60-300 秒

注意:

锁一定要设置 TTL
解锁时要校验 value不能误删别人的锁

4. AI 分析任务状态

AI 分析建议用异步任务。

流程:

App 提交回答
→ 后端创建 ai_analysis_jobs 记录
→ 加入 Redis 队列
→ 返回 jobId
→ Worker 调用 AI
→ 结果写入 MySQL
→ Redis 状态改为 completed

任务状态 key

key:
job:ai-analysis:{jobId}:status

value:
pending / processing / completed / failed

ttl:
24 小时

任务进度 key

key:
job:ai-analysis:{jobId}:progress

value:
0-100

ttl:
24 小时

任务错误信息

key:
job:ai-analysis:{jobId}:error

value:
"AI provider timeout"

ttl:
24 小时

注意:

Redis 只存临时状态
最终任务记录和分析结果必须写入 MySQL
ai_analysis_jobs
ai_analysis_results
focus_items
review_cards

5. 资料导入任务状态

导入资料也建议异步。

场景:

上传 PDF
粘贴长文本
导入链接
AI 解析生成知识点

导入任务状态

key:
job:document-import:{importId}:status

value:
pending / parsing / chunking / generating / completed / failed

ttl:
24 小时

导入进度

key:
job:document-import:{importId}:progress

value:
0-100

ttl:
24 小时

导入处理中提示

key:
job:document-import:{importId}:message

value:
"正在提取关键知识点"

ttl:
24 小时

最终结果写入 MySQL

document_imports
uploaded_files
knowledge_items
knowledge_item_relations
tags

6. BullMQ 队列

如果后端是 Node.js / NestJS建议用 BullMQ。

队列由 BullMQ 自动管理 Redis key不需要你自己建。

建议预留 3 个队列:

ai-analysis
document-import
notification

ai-analysis 队列

任务数据:

{
  "jobId": 123,
  "userId": 456,
  "sessionId": 789,
  "answerId": 1001,
  "jobType": "active_recall_analysis"
}

处理逻辑:

读取用户回答
调用 AI
生成分析结果
写入 ai_analysis_results
生成 focus_items
生成 review_cards
发送通知

document-import 队列

任务数据:

{
  "importId": 123,
  "userId": 456,
  "knowledgeBaseId": 789,
  "sourceType": "file"
}

处理逻辑:

解析文件
提取文本
分段
生成知识点
写入 knowledge_items
更新 document_imports 状态

notification 队列

任务数据:

{
  "userId": 456,
  "type": "review_due",
  "title": "8 张卡片今日到期复习",
  "data": {
    "reviewCount": 8
  }
}

处理逻辑:

写入 notifications 表
后面可扩展推送 APNs

四、Redis Key 总表

缓存类

cache:user:{userId}:profile
cache:user:{userId}:preferences
cache:user:{userId}:knowledge-bases
cache:knowledge-base:{knowledgeBaseId}:summary
cache:review:user:{userId}:due-count

限流类

rate:user:{userId}:ai:daily:{date}
rate:user:{userId}:feedback:hourly
rate:ip:{ip}:request:{minute}
rate:ip:{ip}:login:{date}

锁类

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}

任务状态类

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

会话临时状态

session:learning:{sessionId}:heartbeat
session:learning:{sessionId}:current-step
session:active-recall:{sessionId}:draft

例如用户正在写回答,可以短期保存草稿:

key:
session:active-recall:{sessionId}:draft

ttl:
1-24 小时

最终提交后还是写 MySQL。


Token / 黑名单

auth:refresh-token:blacklist:{tokenId}
auth:access-token:blacklist:{jwtId}

退出登录或注销账号时可用。


五、TTL 建议

用户资料缓存5-10 分钟
知识库列表缓存3-5 分钟
AI 每日限流:到当天结束或 24 小时
IP 请求限流60-120 秒
登录尝试限流10-30 分钟
AI 分析任务状态24 小时
资料导入任务状态24 小时
分布式锁60 秒到 30 分钟,按任务类型决定
学习草稿1-24 小时
Token 黑名单:到 token 原本过期时间

六、Redis 数据类型建议

String

最常用。

用于:

缓存 JSON
计数器
状态
锁

示例:

rate:user:123:ai:daily:2026-05-09 = 8
job:ai-analysis:1001:status = processing

Hash

可选,用于对象字段更新频繁的场景。

例如:

job:ai-analysis:1001
  status = processing
  progress = 40
  message = 正在分析薄弱点

v0.1 也可以先用 String 多 key简单直接。


List / Stream

队列相关,但如果使用 BullMQ不需要自己操作。


Set

可选。

比如记录某天处理过的学习项:

set:user:{userId}:reviewed-items:{date}

Sorted Set

后期可用于按时间排序的任务。

例如:

zset:review:due

但 v0.1 可以先不做,复习到期直接查 MySQL。


七、哪些不要放 Redis

不要把这些只放 Redis

用户资料
知识库内容
知识点内容
学习记录
主动回忆回答
AI 分析结果
待巩固项
复习卡片
复习记录
学习活跃记录
通知记录
用户设置
协议同意记录

这些全部要写 MySQL。

Redis 可以缓存它们,但不是唯一来源。


八、Redis 和 MySQL 的典型组合流程

AI 分析流程

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

资料导入流程

1. MySQL 创建 document_imports
2. Redis 加入 document-import 队列
3. Redis 存导入进度
4. Worker 解析文件
5. MySQL 写 knowledge_items
6. MySQL 更新 document_imports 为 success
7. Redis 状态 completed

学习活跃图流程

1. 用户完成学习动作
2. MySQL 写 learning_records
3. MySQL 更新 daily_learning_activities
4. Redis 可短期缓存今日活跃统计
5. App 查询活跃图时优先查 MySQL必要时加缓存

九、v0.1 Redis 最小落地范围

第一版不用把所有 Redis 场景都做完。

建议先做:

1. Redis 连接
2. /health 检查 Redis
3. RedisService
4. AI 每日调用限流
5. AI 分析队列
6. AI 分析任务状态
7. 防重复提交锁
8. document-import 队列预留
9. notification 队列预留

暂时不做:

复杂缓存策略
Sorted Set 复习调度
复杂分布式任务调度
全量通知推送
复杂排行榜

十、给 Trae 的提示词

请为「知习」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 管过程。