diff --git a/.gitignore b/.gitignore index 02479cc..93366ff 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ coverage/ .cache/ tmp/ temp/docs/credentials.md +docs/credentials.md +docs/AI回答.md diff --git a/docs/AI回答.md b/docs/AI回答.md deleted file mode 100644 index 81fcfc6..0000000 --- a/docs/AI回答.md +++ /dev/null @@ -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" diff --git a/docs/credentials.md b/docs/credentials.md deleted file mode 100644 index 9f735bc..0000000 --- a/docs/credentials.md +++ /dev/null @@ -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 | | -| 用户名 | `admin` | -| 密码 | `Swgr@fmDentAYVXQUpG6oZDpJ` | -| 认证方式 | Basic Auth | - -*** - -## Gitea - -| 项目 | 值 | -| ------------ | ------------------------------------------ | -| URL | | -| 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 -``` -