docs: 补移 AI回答.md 到 docs/
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 11s

This commit is contained in:
WangDL 2026-05-09 20:33:33 +08:00
parent 3e653dc1af
commit 4435e4a8ab
5 changed files with 885 additions and 2430 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,814 +0,0 @@
---
source: AI回答.md
updated: 2026-05-09
---
# 知习 MySQL 数据库表结构设计
> 共 27 张表v0.1 先建 24 张核心表。
---
## 通用字段规范
每张核心表统一使用:
```sql
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL
```
- `id`:内部主键
- `created_at`:创建时间
- `updated_at`:更新时间
- `deleted_at`:软删除
状态字段统一用 `VARCHAR(32)`,不用 MySQL ENUM。
---
## 一、用户与认证表5 张)
### 1. users 用户表
```sql
users
- id BIGINT UNSIGNED PK
- email VARCHAR(255) NULL
- nickname VARCHAR(100) NULL
- avatar_url VARCHAR(500) NULL
- status VARCHAR(32) NOT NULL DEFAULT 'active'
- onboarding_completed TINYINT(1) NOT NULL DEFAULT 0
- last_login_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
- deleted_at DATETIME NULL
```
索引:
```sql
INDEX idx_users_email (email)
INDEX idx_users_status (status)
```
---
### 2. auth_accounts 第三方登录账号表
```sql
auth_accounts
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- provider VARCHAR(32) NOT NULL -- apple
- provider_user_id VARCHAR(255) NOT NULL -- Apple userIdentifier / sub
- email VARCHAR(255) NULL
- raw_profile_json JSON NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_provider_user (provider, provider_user_id)
INDEX idx_auth_accounts_user_id (user_id)
```
---
### 3. refresh_tokens 刷新 Token 表
```sql
refresh_tokens
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- token_hash VARCHAR(255) NOT NULL
- device_id VARCHAR(255) NULL
- device_name VARCHAR(255) NULL
- expires_at DATETIME NOT NULL
- revoked_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_refresh_tokens_user_id (user_id)
INDEX idx_refresh_tokens_token_hash (token_hash)
```
---
### 4. user_profiles 用户资料扩展表
```sql
user_profiles
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- learning_identity VARCHAR(100) NULL -- 系统学习者 / 备考用户 / 知识工作者
- learning_direction VARCHAR(255) NULL -- 认知科学 / AIGC / 产品设计
- bio TEXT NULL
- current_goal VARCHAR(255) NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_user_profiles_user_id (user_id)
```
---
### 5. user_preferences 用户学习偏好表
```sql
user_preferences
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- preferred_methods JSON NULL
-- ["active_recall", "spaced_repetition", "feynman", "retrieval_practice"]
- default_focus_minutes INT NOT NULL DEFAULT 25
- ai_suggestion_level VARCHAR(32) NOT NULL DEFAULT 'normal'
-- low / normal / high
- language VARCHAR(32) NOT NULL DEFAULT 'zh-CN'
- appearance VARCHAR(32) NOT NULL DEFAULT 'system'
- notification_enabled TINYINT(1) NOT NULL DEFAULT 1
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_user_preferences_user_id (user_id)
```
---
## 二、知识库相关表5 张)
### 6. knowledge_bases 知识库表
```sql
knowledge_bases
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- title VARCHAR(255) NOT NULL
- description TEXT NULL
- cover_key VARCHAR(100) NULL
- status VARCHAR(32) NOT NULL DEFAULT 'active'
-- active / archived / deleted
- item_count INT NOT NULL DEFAULT 0
- last_studied_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
- deleted_at DATETIME NULL
```
索引:
```sql
INDEX idx_knowledge_bases_user_id (user_id)
INDEX idx_knowledge_bases_status (status)
```
---
### 7. knowledge_items 知识点/内容表
```sql
knowledge_items
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_base_id BIGINT UNSIGNED NOT NULL
- parent_id BIGINT UNSIGNED NULL
- item_type VARCHAR(32) NOT NULL
-- chapter / lesson / concept / note / imported_doc
- title VARCHAR(255) NOT NULL
- content LONGTEXT NULL
- summary TEXT NULL
- source_type VARCHAR(32) NULL
-- manual / file / url / ai_generated
- source_ref VARCHAR(500) NULL
- order_index INT NOT NULL DEFAULT 0
- status VARCHAR(32) NOT NULL DEFAULT 'active'
- created_at DATETIME
- updated_at DATETIME
- deleted_at DATETIME NULL
```
索引:
```sql
INDEX idx_knowledge_items_user_id (user_id)
INDEX idx_knowledge_items_kb_id (knowledge_base_id)
INDEX idx_knowledge_items_parent_id (parent_id)
INDEX idx_knowledge_items_type (item_type)
```
---
### 8. knowledge_item_relations 知识点关联表
```sql
knowledge_item_relations
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- source_item_id BIGINT UNSIGNED NOT NULL
- target_item_id BIGINT UNSIGNED NOT NULL
- relation_type VARCHAR(32) NOT NULL
-- related / prerequisite / similar / conflict / extension
- confidence DECIMAL(5,2) NULL
- reason TEXT NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_relations_source (source_item_id)
INDEX idx_relations_target (target_item_id)
```
---
### 9. tags 标签表
```sql
tags
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- name VARCHAR(100) NOT NULL
- color VARCHAR(32) NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_user_tag_name (user_id, name)
```
---
### 10. knowledge_item_tags 知识点标签关联表
```sql
knowledge_item_tags
- id BIGINT UNSIGNED PK
- knowledge_item_id BIGINT UNSIGNED NOT NULL
- tag_id BIGINT UNSIGNED NOT NULL
- created_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_item_tag (knowledge_item_id, tag_id)
```
---
## 三、资料导入相关表2 张)
### 11. uploaded_files 上传文件表
```sql
uploaded_files
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- filename VARCHAR(255) NOT NULL
- mime_type VARCHAR(100) NULL
- storage_path VARCHAR(500) NOT NULL
- size_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0
- checksum VARCHAR(255) NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_uploaded_files_user_id (user_id)
```
---
### 12. document_imports 资料导入任务表
```sql
document_imports
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_base_id BIGINT UNSIGNED NULL
- file_id BIGINT UNSIGNED NULL
- source_type VARCHAR(32) NOT NULL
-- file / text / url
- source_name VARCHAR(255) NULL
- source_url VARCHAR(500) NULL
- raw_text LONGTEXT NULL
- status VARCHAR(32) NOT NULL DEFAULT 'pending'
-- pending / processing / success / failed
- progress INT NOT NULL DEFAULT 0
- error_message TEXT NULL
- result_json JSON NULL
- started_at DATETIME NULL
- completed_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_document_imports_user_id (user_id)
INDEX idx_document_imports_status (status)
```
---
## 四、学习过程相关表2 张)
### 13. learning_sessions 学习会话表
```sql
learning_sessions
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_base_id BIGINT UNSIGNED NULL
- knowledge_item_id BIGINT UNSIGNED NULL
- mode VARCHAR(32) NOT NULL
-- reading / active_recall / review / feynman / free_learning
- status VARCHAR(32) NOT NULL DEFAULT 'active'
-- active / completed / cancelled
- started_at DATETIME NOT NULL
- ended_at DATETIME NULL
- duration_seconds INT NOT NULL DEFAULT 0
- focus_minutes INT NULL
- metadata JSON NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_learning_sessions_user_id (user_id)
INDEX idx_learning_sessions_item_id (knowledge_item_id)
INDEX idx_learning_sessions_started_at (started_at)
```
---
### 14. learning_records 学习记录表
类似 GitHub commit log语义是学习记录。
```sql
learning_records
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- session_id BIGINT UNSIGNED NULL
- record_type VARCHAR(32) NOT NULL
-- read / active_recall / review / ai_analysis / focus_item_completed
- title VARCHAR(255) NOT NULL
- description TEXT NULL
- duration_seconds INT NOT NULL DEFAULT 0
- occurred_at DATETIME NOT NULL
- metadata JSON NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_learning_records_user_id (user_id)
INDEX idx_learning_records_occurred_at (occurred_at)
```
---
## 五、主动回忆相关表2 张)
### 15. active_recall_questions 主动回忆问题表
```sql
active_recall_questions
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_item_id BIGINT UNSIGNED NULL
- question_text TEXT NOT NULL
- difficulty VARCHAR(32) NULL
-- easy / normal / hard
- created_by VARCHAR(32) NOT NULL DEFAULT 'ai'
-- ai / user / system
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_recall_questions_user_id (user_id)
INDEX idx_recall_questions_item_id (knowledge_item_id)
```
---
### 16. active_recall_answers 主动回忆回答表
```sql
active_recall_answers
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- question_id BIGINT UNSIGNED NULL
- session_id BIGINT UNSIGNED NULL
- answer_type VARCHAR(32) NOT NULL DEFAULT 'text'
-- text / voice
- answer_text LONGTEXT NULL
- audio_file_id BIGINT UNSIGNED NULL
- submitted_at DATETIME NOT NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_recall_answers_user_id (user_id)
INDEX idx_recall_answers_question_id (question_id)
INDEX idx_recall_answers_session_id (session_id)
```
---
## 六、AI 分析相关表2 张)
### 17. ai_analysis_jobs AI 分析任务表
```sql
ai_analysis_jobs
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- session_id BIGINT UNSIGNED NULL
- answer_id BIGINT UNSIGNED NULL
- job_type VARCHAR(32) NOT NULL
-- active_recall_analysis / weak_point_detection / review_generation
- status VARCHAR(32) NOT NULL DEFAULT 'pending'
-- pending / processing / success / failed
- progress INT NOT NULL DEFAULT 0
- error_message TEXT NULL
- queued_at DATETIME NULL
- started_at DATETIME NULL
- completed_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_ai_jobs_user_id (user_id)
INDEX idx_ai_jobs_status (status)
INDEX idx_ai_jobs_session_id (session_id)
```
---
### 18. ai_analysis_results AI 分析结果表
```sql
ai_analysis_results
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- job_id BIGINT UNSIGNED NOT NULL
- session_id BIGINT UNSIGNED NULL
- answer_id BIGINT UNSIGNED NULL
- summary TEXT NULL
- mastery_score INT NULL -- 0-100
- strengths JSON NULL
- weaknesses JSON NULL
- suggestions JSON NULL
- next_actions JSON NULL
- raw_result JSON NULL
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_ai_results_user_id (user_id)
INDEX idx_ai_results_job_id (job_id)
INDEX idx_ai_results_session_id (session_id)
```
---
## 七、待巩固项表1 张)
### 19. focus_items 待巩固项表
类似 GitHub issue学习语义叫「待巩固项」。
```sql
focus_items
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_base_id BIGINT UNSIGNED NULL
- knowledge_item_id BIGINT UNSIGNED NULL
- analysis_result_id BIGINT UNSIGNED NULL
- title VARCHAR(255) NOT NULL
- reason TEXT NULL
- suggestion TEXT NULL
- priority VARCHAR(32) NOT NULL DEFAULT 'normal'
-- low / normal / high
- status VARCHAR(32) NOT NULL DEFAULT 'open'
-- open / in_review / completed / ignored
- mastery_score INT NULL
- due_at DATETIME NULL
- completed_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
- deleted_at DATETIME NULL
```
索引:
```sql
INDEX idx_focus_items_user_id (user_id)
INDEX idx_focus_items_status (status)
INDEX idx_focus_items_due_at (due_at)
```
---
## 八、复习相关表3 张)
### 20. review_cards 复习卡片表
```sql
review_cards
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- knowledge_item_id BIGINT UNSIGNED NULL
- focus_item_id BIGINT UNSIGNED NULL
- front_text TEXT NOT NULL
- back_text TEXT NULL
- difficulty VARCHAR(32) NULL
- status VARCHAR(32) NOT NULL DEFAULT 'active'
-- active / suspended / completed
- next_review_at DATETIME NULL
- interval_days INT NOT NULL DEFAULT 1
- ease_factor DECIMAL(4,2) NOT NULL DEFAULT 2.50
- repetition_count INT NOT NULL DEFAULT 0
- lapse_count INT NOT NULL DEFAULT 0
- created_at DATETIME
- updated_at DATETIME
- deleted_at DATETIME NULL
```
索引:
```sql
INDEX idx_review_cards_user_id (user_id)
INDEX idx_review_cards_next_review_at (next_review_at)
INDEX idx_review_cards_focus_item_id (focus_item_id)
```
---
### 21. review_logs 复习记录表
```sql
review_logs
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- review_card_id BIGINT UNSIGNED NOT NULL
- session_id BIGINT UNSIGNED NULL
- rating VARCHAR(32) NOT NULL
-- again / hard / good / easy
- response_text TEXT NULL
- reviewed_at DATETIME NOT NULL
- next_review_at DATETIME NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_review_logs_user_id (user_id)
INDEX idx_review_logs_card_id (review_card_id)
INDEX idx_review_logs_reviewed_at (reviewed_at)
```
---
### 22. review_plans 复习计划表
```sql
review_plans
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- title VARCHAR(255) NOT NULL
- status VARCHAR(32) NOT NULL DEFAULT 'active'
-- active / completed / cancelled
- scheduled_at DATETIME NULL
- completed_at DATETIME NULL
- card_count INT NOT NULL DEFAULT 0
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_review_plans_user_id (user_id)
INDEX idx_review_plans_scheduled_at (scheduled_at)
```
---
## 九、学习活跃记录表1 张)
### 23. daily_learning_activities 每日学习活跃表
用于个人中心的蓝色学习活跃图。
```sql
daily_learning_activities
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- activity_date DATE NOT NULL
- duration_seconds INT NOT NULL DEFAULT 0
- sessions_count INT NOT NULL DEFAULT 0
- active_recall_count INT NOT NULL DEFAULT 0
- review_count INT NOT NULL DEFAULT 0
- ai_analysis_count INT NOT NULL DEFAULT 0
- completed_loop_count INT NOT NULL DEFAULT 0
- activity_level INT NOT NULL DEFAULT 0 -- 0-4颜色深浅
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
UNIQUE KEY uk_user_activity_date (user_id, activity_date)
INDEX idx_daily_activity_user_id (user_id)
```
---
## 十、通知与反馈表2 张)
### 24. notifications 消息通知表
```sql
notifications
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- type VARCHAR(32) NOT NULL
-- review_due / ai_analysis_done / learning_suggestion / system
- title VARCHAR(255) NOT NULL
- content TEXT NULL
- data JSON NULL
- read_at DATETIME NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_notifications_user_id (user_id)
INDEX idx_notifications_read_at (read_at)
INDEX idx_notifications_type (type)
```
---
### 25. feedbacks 用户反馈表
```sql
feedbacks
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NULL
- email VARCHAR(255) NULL
- category VARCHAR(64) NOT NULL
-- feature / bug / experience / privacy / other
- content TEXT NOT NULL
- device_info JSON NULL
- status VARCHAR(32) NOT NULL DEFAULT 'open'
-- open / processing / resolved / ignored
- created_at DATETIME
- updated_at DATETIME
```
索引:
```sql
INDEX idx_feedbacks_user_id (user_id)
INDEX idx_feedbacks_status (status)
```
---
## 十一、合规与系统表2 张)
### 26. user_consents 用户协议同意记录表
```sql
user_consents
- id BIGINT UNSIGNED PK
- user_id BIGINT UNSIGNED NOT NULL
- consent_type VARCHAR(32) NOT NULL
-- privacy_policy / terms_of_service
- version VARCHAR(50) NOT NULL
- accepted_at DATETIME NOT NULL
- ip_address VARCHAR(100) NULL
- user_agent VARCHAR(500) NULL
- created_at DATETIME
```
索引:
```sql
INDEX idx_user_consents_user_id (user_id)
INDEX idx_user_consents_type (consent_type)
```
---
### 27. app_changelogs 更新记录表(可选)
```sql
app_changelogs
- id BIGINT UNSIGNED PK
- version VARCHAR(50) NOT NULL
- title VARCHAR(255) NOT NULL
- content TEXT NOT NULL
- platform VARCHAR(32) NOT NULL DEFAULT 'ios'
- published_at DATETIME NULL
- created_at DATETIME
- updated_at DATETIME
```
---
## v0.1 建表优先级
### 第一批24 张,必须)
```text
users
auth_accounts
refresh_tokens
user_profiles
user_preferences
knowledge_bases
knowledge_items
tags
knowledge_item_tags
document_imports
uploaded_files
learning_sessions
learning_records
active_recall_questions
active_recall_answers
ai_analysis_jobs
ai_analysis_results
focus_items
review_cards
review_logs
daily_learning_activities
notifications
feedbacks
user_consents
```
### 第二批3 张,可稍后)
```text
knowledge_item_relations
review_plans
app_changelogs
```
---
## 模块与表对应关系
```text
auth → users, auth_accounts, refresh_tokens
users → user_profiles, user_preferences, user_consents
knowledge-base → knowledge_bases
knowledge-items → knowledge_items, knowledge_item_relations, tags, knowledge_item_tags
document-import → uploaded_files, document_imports
learning-session → learning_sessions, learning_records
active-recall → active_recall_questions, active_recall_answers
ai-analysis → ai_analysis_jobs, ai_analysis_results
focus-items → focus_items
review → review_cards, review_logs, review_plans
learning-activity → daily_learning_activities
notifications → notifications
feedback → feedbacks
system → app_changelogs
```
---
## Prisma 生成规范
```text
所有表使用 BIGINT UNSIGNED AUTO_INCREMENT 主键
状态字段使用 VARCHAR不使用 ENUM
JSON 字段用于存储 AI 分析结构化结果、用户偏好、元数据
核心表添加 created_at、updated_at、deleted_at
为 user_id、status、created_at、外键字段添加合理索引
```

View File

@ -1,262 +0,0 @@
---
source: AI回答.md
updated: 2026-05-09
---
# 知习 Redis 设计
> Redis 在知习里不是"另一个 MySQL",它是系统的**加速器和调度器**。MySQL 存结果Redis 管过程。
---
## 1. Redis 定位
Redis 不作为主数据库,只负责:
1. 缓存
2. 限流
3. 队列BullMQ
4. 临时任务状态
5. 分布式锁
6. 防重复提交
7. AI 调用次数统计
8. 短期 Token / 黑名单
9. 通知任务调度
10. 学习会话草稿
---
## 2. 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
```
规则:
1. 全部小写
2. 用冒号 `:` 分隔
3. 从大范围到小范围
4. userId、jobId、sessionId 明确写在 key 里
5. 带日期的 key 用 `YYYY-MM-DD`
6. 所有临时 key 必须设置 TTL
---
## 3. Key 总表
### 缓存类
| Key | 用途 | TTL |
|-----|------|-----|
| `cache:user:{userId}:profile` | 用户资料 | 5-10 分钟 |
| `cache:user:{userId}:preferences` | 用户偏好设置 | 10 分钟 |
| `cache:user:{userId}:knowledge-bases` | 用户知识库列表 | 3-5 分钟 |
| `cache:knowledge-base:{kbId}:summary` | 知识库摘要 | 5 分钟 |
| `cache:review:user:{userId}:due-count` | 到期复习数量 | 1-3 分钟 |
### 限流类
| Key | 用途 | TTL |
|-----|------|-----|
| `rate:user:{userId}:ai:daily:{date}` | 用户每日 AI 调用次数 | 到当天结束或 24h |
| `rate:user:{userId}:feedback:hourly` | 用户每小时反馈次数 | 1 小时 |
| `rate:ip:{ip}:request:{minute}` | IP 每分钟请求频率 | 60-120 秒 |
| `rate:ip:{ip}:login:{date}` | IP 每日登录尝试 | 10-30 分钟 |
### 分布式锁类
| Key | 用途 | TTL |
|-----|------|-----|
| `lock:ai-analysis:session:{sessionId}` | 防止重复提交 AI 分析 | 60-300 秒 |
| `lock:ai-analysis:answer:{answerId}` | 防止同回答重复分析 | 60-300 秒 |
| `lock:document-import:{importId}` | 防止重复处理导入 | 5-30 分钟 |
| `lock:review-plan:user:{userId}:item:{itemId}` | 防止重复生成复习计划 | 60-300 秒 |
| `lock:feedback:ip:{ip}` | 防止 IP 刷反馈 | 60-300 秒 |
### 任务状态类
| Key | Value 示例 | TTL |
|-----|-----------|-----|
| `job:ai-analysis:{jobId}:status` | `pending / processing / completed / failed` | 24h |
| `job:ai-analysis:{jobId}:progress` | `0-100` | 24h |
| `job:ai-analysis:{jobId}:error` | 错误信息字符串 | 24h |
| `job:document-import:{importId}:status` | `pending / parsing / chunking / generating / completed / failed` | 24h |
| `job:document-import:{importId}:progress` | `0-100` | 24h |
| `job:document-import:{importId}:message` | `"正在提取关键知识点"` | 24h |
| `job:document-import:{importId}:error` | 错误信息字符串 | 24h |
### 会话临时状态类
| Key | 用途 | TTL |
|-----|------|-----|
| `session:learning:{sessionId}:heartbeat` | 学习会话心跳 | 30 分钟 |
| `session:learning:{sessionId}:current-step` | 当前学习步骤 | 2 小时 |
| `session:active-recall:{sessionId}:draft` | 回答草稿暂存 | 1-24 小时 |
### Token / 黑名单
| Key | 用途 | TTL |
|-----|------|-----|
| `auth:refresh-token:blacklist:{tokenId}` | 注销后刷新 Token 失效 | 到 token 过期 |
| `auth:access-token:blacklist:{jwtId}` | 注销后 JWT 失效 | 到 token 过期 |
### Set 类(可选)
| Key | 用途 |
|-----|------|
| `set:user:{userId}:reviewed-items:{date}` | 当天已复习项去重 |
---
## 4. Redis 数据类型选择
| 类型 | 用途 | 示例 |
|------|------|------|
| **String** | 最常用:缓存 JSON、计数器、状态、锁 | `rate:user:123:ai:daily:2026-05-09 = 8` |
| **Hash** | 可选,任务多字段频繁更新的场景 | `job:ai-analysis:1001 → status=processing, progress=40` |
| **List/Stream** | 队列BullMQ 自动管理,不需要手动操作 | - |
| **Set** | 去重,如当天已复习项集合 | `set:user:123:reviewed-items:2026-05-09` |
| **Sorted Set** | 后期按时间排序的复习调度v0.1 先不做 | - |
---
## 5. 核心流程中 Redis 与 MySQL 的配合
### 5.1 AI 分析流程
```text
1. MySQL 创建 ai_analysis_jobs
2. Redis 加入 ai-analysis 队列BullMQ
3. Redis 存 job:xxx:status = processing
4. Worker 调用 AI
5. MySQL 写 ai_analysis_results
6. MySQL 写 focus_items
7. MySQL 写 review_cards
8. Redis 存 job:xxx:status = completed
9. MySQL 写 notifications
```
### 5.2 资料导入流程
```text
1. MySQL 创建 document_imports
2. Redis 加入 document-import 队列BullMQ
3. Redis 存导入进度
4. Worker 解析文件
5. MySQL 写 knowledge_items
6. MySQL 更新 document_imports 为 success
7. Redis 存状态 completed
```
### 5.3 学习活跃图流程
```text
1. 用户完成学习动作
2. MySQL 写 learning_records
3. MySQL 更新 daily_learning_activities
4. Redis 可短期缓存今日活跃统计
5. App 查询活跃图优先查 MySQL必要时加缓存
```
---
## 6. BullMQ 队列
BullMQ 自动管理 Redis key不需要手动建。建议预留 3 个队列:
| 队列名 | 任务数据 | 处理逻辑 |
|--------|---------|---------|
| `ai-analysis` | `{ jobId, userId, sessionId, answerId, jobType }` | 读取回答 → 调 AI → 写结果 → 生成待巩固项 → 生成复习卡片 → 发通知 |
| `document-import` | `{ importId, userId, knowledgeBaseId, sourceType }` | 解析文件 → 提取文本 → 分段 → 生成知识点 → 写 knowledge_items → 更新状态 |
| `notification` | `{ userId, type, title, data }` | 写 notifications 表,后续可扩展 APNs 推送 |
---
## 7. 哪些绝对不能只放 Redis
以下全部必须写 MySQLRedis 只能做缓存,不是唯一来源:
```text
用户资料 → users, user_profiles
知识库内容 → knowledge_bases
知识点内容 → knowledge_items
学习记录 → learning_records
主动回忆回答 → active_recall_answers
AI 分析结果 → ai_analysis_results
待巩固项 → focus_items
复习卡片 → review_cards
复习记录 → review_logs
学习活跃记录 → daily_learning_activities
通知记录 → notifications
用户设置 → user_preferences
协议同意记录 → user_consents
```
---
## 8. v0.1 Redis 最小落地范围
### 必须做
```text
1. Redis 连接
2. /health 检查 Redis
3. RedisModule + RedisServiceget/set/del/exists/expire/ttl/incr/setNx/lock/unlock
4. AI 每日调用限流rate:user:{userId}:ai:daily:{date}
5. AI 分析队列BullMQ ai-analysis
6. AI 分析任务状态job:ai-analysis:{jobId}:status/progress/error
7. 防重复提交锁lock:ai-analysis:session:{sessionId}
8. document-import 队列预留BullMQ document-import
9. notification 队列预留BullMQ notification
```
### 暂时不做
```text
复杂缓存策略
Sorted Set 复习调度
复杂分布式任务调度
全量通知推送APNs
复杂排行榜
```
---
## 9. RedisService 方法清单
```text
get(key) — 读取
set(key, value) — 写入
del(key) — 删除
exists(key) — 判断存在
expire(key, ttl) — 设置过期
ttl(key) — 查看剩余时间
incr(key) — 自增(限流计数)
setNx(key, value) — 不存在才写入(锁)
lock(key, ttl) — 获取分布式锁,返回 token
unlock(key, token) — 释放锁,校验 token防止误删
```
锁的实现注意:
- 锁必须设置 TTL
- 解锁时必须校验 value/token不能误删别人的锁
- 锁的 value 用随机 token解锁时比对
---
## 10. 一句话总结
> **Redis 在知习里不是"另一个 MySQL"它是系统的加速器和调度器。MySQL 存结果Redis 管过程。**

View File

@ -1,169 +0,0 @@
# 知习 api-server 安全基线
> v0.1 安全设计文档。本后端存储用户资料、知识库、上传文件、主动回忆回答、AI 分析结果和学习记录,第一版必须建立基础安全边界。
---
## 1. 全局安全中间件
| 措施 | 实现 | 文件 |
|------|------|------|
| helmet | `app.use(helmet())` 设置安全 HTTP 头 | `src/main.ts` |
| CORS | 仅允许配置域名。生产环境仅允许 `longde.cloud` | `src/main.ts` |
| body size limit | JSON 请求体最大 10MB | `src/main.ts` |
| 异常过滤 | 生产环境不返回 stack trace | `src/common/filters/global-exception.filter.ts` |
---
## 2. 认证与 Token
### JWT
- `accessToken`: JWT1 小时过期
- `refreshToken`: 128 位随机 hex入库只存 SHA-256 hash
- logout 时 `revokedAt = now()` 撤销所有 refresh token
- `/users/me` 及其所有子路由强制 `@UseGuards(JwtAuthGuard)`
```
POST /auth/apple → 返回 accessToken + refreshToken
POST /auth/refresh → 消耗旧 refreshToken发放新 token pairrotation
POST /auth/logout → 撤销该用户所有 refresh token
```
### 存储安全
```
refresh_tokens.tokenHash = SHA-256(实际 token)
数据库中永远不存明文 refreshToken
```
---
## 3. 权限与越权防护
### 资源归属校验
所有用户资源操作必须校验 `userId` 归属:
```ts
// src/common/utils/security.util.ts
export async function findByIdAndUserId(delegate, id, userId, resourceName)
export function ensureOwnership(record, userId, resourceName)
```
### 需校验的资源
| 资源 | 校验字段 |
|------|---------|
| KnowledgeBase | `userId` |
| KnowledgeItem | `userId` |
| LearningSession | `userId` |
| ActiveRecallAnswer | `userId` |
| AiAnalysisJob | `userId` |
| AiAnalysisResult | `userId` |
| FocusItem | `userId` |
| ReviewCard | `userId` |
| ReviewLog | `userId` |
| DocumentImport | `userId` |
---
## 4. 参数校验
- 全局 `StrictValidationPipe`:
- `whitelist: true` — 自动剥离未声明字段
- `forbidNonWhitelisted: true` — 未知字段返回 400
- 字符串字段最大长度 5000 字符
- 分页 DTO: page≥1, limit 1-100
---
## 5. 限流Redis
| 场景 | Key | 限制 |
|------|-----|------|
| 登录 | `rate:ip:{ip}:login:{date}` | 20次/IP/天 |
| 反馈 | `rate:ip:{ip}:feedback:hourly` | 5次/IP/时 |
| AI 分析 | `rate:user:{userId}:ai:daily:{date}` | 50次/用户/天 |
| 文件上传 | `rate:user:{userId}:upload:hourly` | 10次/用户/时 |
实现: `src/common/utils/rate-limit.service.ts`
---
## 6. 文件上传安全
| 措施 | 说明 |
|------|------|
| 类型白名单 | PDF, Word, Excel, 纯文本, Markdown, CSV, PNG, JPEG, WebP |
| 大小限制 | 最大 20MB |
| 随机文件名 | `sanitizeFilename()` 生成随机 key不信任用户原始文件名 |
| 默认私有 | 所有文件默认私有访问 |
| 路径隔离 | `users/{userId}/...` |
---
## 7. Redis 安全使用
- 不存核心业务结果(用户资料/知识点/AI分析结果等必须在 MySQL
- 队列任务只存 `jobId`/`userId` 等引用 ID
- 所有临时 key 必须设置 TTL
- 防重复提交锁必须有 TTL解锁校验 token
- 不在 Redis 中存 token 明文
---
## 8. COS 安全使用
- Bucket 默认私有读写
- 后端不向前端暴露 SecretId/SecretKey
- 下载私有文件通过签名 URL
- 上传路径按 `users/{userId}/{randomKey}` 组织
- 预留临时上传 URLSTS机制
---
## 9. Swagger 安全
- 开发环境默认开启
- 生产环境默认关闭
- 生产环境如需开启,必须配置 Basic Auth`SWAGGER_USER`/`SWAGGER_PASSWORD`
- 生产环境手动设置 `ENABLE_SWAGGER=true`
---
## 10. 数据库安全
- 不使用 root 连接业务
- 业务账号 `zhixi_user` 仅需 SELECT/INSERT/UPDATE/DELETE
- 迁移账号和业务账号分离(`prisma db push` 与运行时连接帐号可不同)
- 数据库自动备份建议: `mysqldump zhixi | gzip > backup-$(date +%Y%m%d).sql.gz`
### 日志中禁止打印
```
DATABASE_URL含密码
JWT_SECRET
AI_API_KEY
COS SecretKey
用户完整 refreshToken
用户上传文件的完整内容
Authorization header
```
---
## 11. 安全检查清单
- [x] helmet 已启用
- [x] CORS 仅允许白名单域名
- [x] JWT + refresh token rotation + hash 存储
- [x] logout 撤销 refresh token
- [x] 所有用户数据接口需要认证
- [x] 资源所有权校验工具已就绪
- [x] StrictValidationPipe 全局启用whitelist + forbidNonWhitelisted
- [x] Redis 限流已实现
- [x] 文件类型/大小白名单
- [x] 全局异常过滤器生产环境不暴露 stack trace
- [x] Swagger 生产环境默认关闭
- [x] 敏感信息不在日志中打印原则已确立

885
docs/AI回答.md Normal file
View File

@ -0,0 +1,885 @@
([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"