861 lines
26 KiB
Markdown
861 lines
26 KiB
Markdown
# 知习数据库与服务器部署方案(最终版)
|
||
|
||
> 定版日期:2026-05-18 | 状态:已拍板,按此执行 | 最后检查:2026-05-20 14:00
|
||
>
|
||
> 完成度标记:✅ 已完成 | 🔶 部分完成 | ⏳ 待完成 | ❌ 未开始
|
||
|
||
---
|
||
|
||
## 一、存储架构总览 ✅ 已完成
|
||
|
||
知识库不需要 MongoDB。最终存储分成四类:
|
||
|
||
```text
|
||
MySQL :权威业务数据(用户、知识库、学习记录、额度、审计)
|
||
Qdrant :向量索引(chunk embedding、语义检索)
|
||
COS :对象存储(原始文件、解析结果、备份快照)
|
||
Redis :队列 / 缓存 / 限流 / 锁
|
||
```
|
||
|
||
不引入的组件:
|
||
|
||
```text
|
||
MongoDB → 不需要(没有文档型存储场景)
|
||
Elasticsearch → 第一阶段不需要(Qdrant + rerank 够用)
|
||
ClickHouse → 第一阶段不需要(OLAP 后续再说)
|
||
```
|
||
|
||
---
|
||
|
||
## 二、MySQL:唯一权威业务数据库 ✅ 已完成
|
||
|
||
### 存放内容
|
||
|
||
```text
|
||
# 用户与认证
|
||
users
|
||
auth_accounts
|
||
refresh_tokens
|
||
memberships
|
||
membership_plans
|
||
|
||
# 知识库核心
|
||
files
|
||
knowledge_bases
|
||
knowledge_sources
|
||
document_imports
|
||
knowledge_chunks
|
||
import_candidates
|
||
knowledge_items
|
||
|
||
# 学习引擎
|
||
active_recall_answers
|
||
ai_analysis_results
|
||
focus_items
|
||
review_cards
|
||
learning_activities
|
||
chat_sessions
|
||
chat_messages
|
||
|
||
# 运营与审计
|
||
ai_usage_logs
|
||
quota_usage
|
||
admin_audit_logs
|
||
backup_jobs
|
||
feedback
|
||
notifications
|
||
```
|
||
|
||
### ID 类型(重要)✅ 已改为 String(cuid)
|
||
|
||
当前 Prisma schema 主键是 `BigInt @default(autoincrement())`,JavaScript/JSON 对 64 位整数有精度问题。
|
||
|
||
**现在数据库空,必须立即改:**
|
||
|
||
```prisma
|
||
id String @id @default(cuid())
|
||
```
|
||
|
||
推荐 `cuid/cuid2`:适合业务 ID,前端、后端、日志、JWT、API 都好处理。以后数据多了再改会很痛苦。
|
||
|
||
### 生产配置 ✅ 已应用
|
||
|
||
文件:`/etc/mysql/conf.d/zhixi.cnf`
|
||
|
||
```ini
|
||
[mysqld]
|
||
# InnoDB
|
||
innodb_buffer_pool_size = 8G
|
||
innodb_buffer_pool_instances = 4
|
||
innodb_log_file_size = 1G
|
||
innodb_flush_log_at_trx_commit = 1
|
||
innodb_file_per_table = 1
|
||
|
||
# Connections
|
||
max_connections = 100
|
||
wait_timeout = 300
|
||
interactive_timeout = 300
|
||
|
||
# Charset
|
||
character-set-server = utf8mb4
|
||
collation-server = utf8mb4_unicode_ci
|
||
|
||
# Slow query
|
||
slow_query_log = 1
|
||
long_query_time = 1
|
||
log_queries_not_using_indexes = 0
|
||
|
||
# Binlog(无主从复制时可关)
|
||
skip-log-bin
|
||
```
|
||
|
||
### 32G 内存分配 ✅ 按方案执行
|
||
|
||
```text
|
||
MySQL buffer pool 8G
|
||
Qdrant 8G–12G(动态)
|
||
Redis 1G 内
|
||
RAG Worker / 解析 4G–8G
|
||
系统 + Docker + 缓存 4G+
|
||
预留安全空间 4G+
|
||
```
|
||
|
||
后续调整规则:
|
||
|
||
```text
|
||
MySQL 慢查询多 + 内存充足 → buffer pool 调到 10G–12G
|
||
Qdrant / Worker 内存吃紧 → 不再加 MySQL 内存
|
||
Too many connections → max_connections 调到 150
|
||
|
||
---
|
||
|
||
## 三、Qdrant:向量数据库 ✅ 已完成
|
||
|
||
### 存放内容
|
||
|
||
```text
|
||
Collection:zhixi_chunks
|
||
├─ chunk embedding 向量(1024d,Cosine)
|
||
├─ userId / knowledgeBaseId / sourceId / chunkId(payload 索引)
|
||
├─ pageNumber / sectionTitle(元数据)
|
||
└─ deleted(bool,软删除标记)
|
||
```
|
||
|
||
### 负责的能力
|
||
|
||
```text
|
||
语义检索(ANN Top-50 → rerank Top-5~8)
|
||
知识库问答召回
|
||
相似知识点查找
|
||
学习内容推荐
|
||
```
|
||
|
||
### 不负责
|
||
|
||
```text
|
||
用户体系
|
||
会员额度
|
||
知识点管理
|
||
学习记录
|
||
订单支付
|
||
```
|
||
|
||
Qdrant 是 MySQL 的补充,不是替代。
|
||
|
||
### 安全策略(已拍板)
|
||
|
||
```text
|
||
第一阶段:不公网暴露 Qdrant
|
||
优先方案:不映射端口,只在 Docker internal network 用容器名访问
|
||
调试方案:仅绑定 127.0.0.1:6333
|
||
暂不启用 API Key,但预留 QDRANT_API_KEY 环境变量
|
||
未来跨服务器访问时 → 必须启用 API Key
|
||
```
|
||
|
||
### Docker Compose 推荐写法(不映射端口)
|
||
|
||
```yaml
|
||
services:
|
||
qdrant:
|
||
image: qdrant/qdrant:latest
|
||
restart: unless-stopped
|
||
volumes:
|
||
- /data/qdrant:/qdrant/storage
|
||
networks:
|
||
- zhixi_internal
|
||
# 不写 ports,公网访问不到
|
||
|
||
backend:
|
||
image: zhixi-backend:latest
|
||
restart: unless-stopped
|
||
environment:
|
||
QDRANT_URL: http://qdrant:6333
|
||
networks:
|
||
- zhixi_internal
|
||
- zhixi_public
|
||
|
||
networks:
|
||
zhixi_internal:
|
||
internal: true # 不对外暴露
|
||
zhixi_public:
|
||
```
|
||
|
||
### 如需宿主机调试(仅绑定 localhost)
|
||
|
||
```yaml
|
||
services:
|
||
qdrant:
|
||
ports:
|
||
- "127.0.0.1:6333:6333"
|
||
- "127.0.0.1:6334:6334"
|
||
```
|
||
|
||
### 不要这样写
|
||
|
||
```yaml
|
||
ports:
|
||
- "6333:6333" # 暴露公网!没有 API Key 时非常危险
|
||
```
|
||
|
||
---
|
||
|
||
## 四、COS:对象存储 ✅ 凭据已配置,Bucket 已验证
|
||
|
||
### 存放内容
|
||
|
||
```text
|
||
zhixi-prod/
|
||
├─ users/{userId}/knowledge-bases/... ← 原始文件 + 解析结果
|
||
├─ users/{userId}/profile/avatar/... ← 头像
|
||
├─ users/{userId}/feedback/... ← 反馈截图
|
||
├─ system/knowledge-bases/... ← 系统内置知识库
|
||
├─ system/backups/qdrant/{date}/... ← Qdrant 快照
|
||
├─ system/backups/mysql/{date}/... ← MySQL 备份
|
||
├─ exports/users/{userId}/... ← 用户导出
|
||
└─ public/app-assets/... ← 公共资源
|
||
```
|
||
|
||
### 原则
|
||
|
||
```text
|
||
数据库是主关系,COS 是文件仓库
|
||
权限、归属、状态永远以数据库为准
|
||
处理文件时从 COS 临时拉取,处理完删除本地临时文件
|
||
```
|
||
|
||
---
|
||
|
||
## 五、Redis:队列与缓存 ✅ 已完成(BullMQ document-import 队列已运行)
|
||
|
||
### 负责
|
||
|
||
```text
|
||
BullMQ 任务队列(文档导入、AI 分析、通知发送)
|
||
API 限流
|
||
分布式锁(防止重复导入、重复扣额度)
|
||
用户 session(备选,也可用 MySQL)
|
||
临时状态缓存
|
||
```
|
||
|
||
### 不负责
|
||
|
||
```text
|
||
长期业务数据
|
||
向量索引
|
||
文件存储
|
||
```
|
||
|
||
---
|
||
|
||
## 六、服务器分工(已拍板)✅ 按方案执行
|
||
|
||
### 总原则
|
||
|
||
现在数据库基本空,**不要再把新表建到旧服务器上**。唯一权威 MySQL 放 8核32G。
|
||
|
||
### 8核32G CVM:正式生产主服务器
|
||
|
||
**部署清单:**
|
||
|
||
```text
|
||
/opt/zhixi/backend ← NestJS 主后端
|
||
/opt/zhixi/rag-worker ← Python RAG Worker
|
||
/opt/zhixi/deploy ← docker-compose.yml + 脚本
|
||
|
||
/data/docker ← Docker data-root
|
||
/data/mysql ← MySQL 数据文件
|
||
/data/redis ← Redis 数据文件
|
||
/data/qdrant ← Qdrant 存储
|
||
/data/tmp/imports ← 临时下载/解析工作区
|
||
/data/logs ← 统一日志
|
||
/data/worker-cache ← llama-index 缓存
|
||
/data/backups/mysql ← MySQL 每日备份
|
||
/data/backups/qdrant ← Qdrant 每日快照
|
||
```
|
||
|
||
**运行服务:**
|
||
|
||
```text
|
||
Nginx(可选)
|
||
NestJS API(Node)
|
||
MySQL 8.0
|
||
Redis 7
|
||
Qdrant(Docker)
|
||
RAG Worker(Python)
|
||
AI Gateway Worker(Node)
|
||
Backup Worker(Cron)
|
||
Cron Jobs(定时清理、stale job recovery)
|
||
```
|
||
|
||
**负责的业务:**
|
||
|
||
```text
|
||
全部用户数据、认证、会员
|
||
全部知识库数据(表 + 向量)
|
||
全部学习引擎(主动回忆、AI 诊断、复习)
|
||
全部 AI 调用与成本记录
|
||
全部后台管理与审计
|
||
```
|
||
|
||
### 4核4G 轻量云:工具服务器 / 辅助服务器
|
||
|
||
**定位:** 继续当工具服务器,不承载生产核心数据。
|
||
|
||
**已运行服务(保留):**
|
||
|
||
```text
|
||
Web 产品页 / landing page
|
||
Gitea
|
||
```
|
||
|
||
**适合新增的服务:**
|
||
|
||
```text
|
||
n8n ← 营销自动化、流程编排、Webhook
|
||
轻量 agent runner ← CI/CD 辅助、定时调研、通知
|
||
Uptime Kuma ← 服务监控
|
||
跳板机 ← SSH 入口
|
||
测试 / staging 环境 ← 预发布验证
|
||
Gitea Webhook 自动化 ← CI/CD 触发
|
||
营销自动化脚本 ← 定时任务
|
||
轻量后台工具 ← 不操作生产库的管理工具
|
||
```
|
||
|
||
**不建议放 4核4G 的服务:**
|
||
|
||
```text
|
||
正式 MySQL / Redis / Qdrant ← 生产核心数据
|
||
RAG Worker / 文档解析 ← 重型 CPU/内存任务
|
||
Dify 生产环境 ← 最低 4G 但跑不稳(后面细说)
|
||
本地大模型 / 多模态模型 ← GPU/内存不够
|
||
重型爬虫 / 大量自动化任务 ← 吃满 CPU
|
||
```
|
||
|
||
---
|
||
|
||
## 6.5、两服务器内网互联 ✅ 已验证
|
||
|
||
| 项目 | 值 |
|
||
|------|-----|
|
||
| 8核32G 内网 IP | 172.21.0.4 |
|
||
| 4核4G 内网 IP | 10.2.0.7 |
|
||
| 延迟 | ~1.9ms(双向 ping) |
|
||
| 通信原则 | **所有服务器间通信均走内网,不走公网** |
|
||
|
||
### 已验证的通信路径
|
||
|
||
| 路径 | 内网地址 | 验证结果 |
|
||
|------|---------|---------|
|
||
| 8核32G → 4核4G Gitea | `http://10.2.0.7:3000` | ✅ HTTP 200, 6.5ms |
|
||
| 4核4G → 8核32G API | `http://172.21.0.4:3000` | ✅ 正常响应 |
|
||
| 8核32G Runner 注册 | `http://10.2.0.7:3000` | ✅ 已切换,restart 正常 |
|
||
|
||
### 对内网通信的服务
|
||
|
||
| 服务 | 原地址 | 切换后 |
|
||
|------|--------|--------|
|
||
| zhixi-prod-runner → Gitea | `81.70.187.179`(公网) | `10.2.0.7`(内网) |
|
||
| 4核4G CI/CD → 8核32G API | `api.longde.cloud` | 可切 `172.21.0.4`(待优化) |
|
||
| COS 上传/下载 | `cos.ap-beijing.myqcloud.com`(内网) | 同区 VPC 内网,免流量费 |
|
||
|
||
---
|
||
|
||
## 七、4核4G 上各服务决策 ✅ 已定案
|
||
|
||
### 1. n8n:可以放
|
||
|
||
n8n 适合放 4核4G,用来做:
|
||
|
||
```text
|
||
营销自动化
|
||
内容生产流程编排
|
||
Gitea Webhook 触发
|
||
定时任务
|
||
数据同步
|
||
通知提醒
|
||
AI API 调用编排
|
||
运营脚本
|
||
```
|
||
|
||
部署方式:
|
||
|
||
```text
|
||
Docker Compose
|
||
nginx/caddy 反代 → https://n8n.yourdomain.com
|
||
```
|
||
|
||
安全要求:
|
||
|
||
```text
|
||
强密码
|
||
HTTPS
|
||
禁止公开注册
|
||
后台路径不裸奔
|
||
定期备份 n8n 数据目录
|
||
```
|
||
|
||
**核心规则:n8n 不直接操作生产数据库。**
|
||
|
||
正确方式:
|
||
|
||
```text
|
||
n8n / agent
|
||
→ 调用 8核32G 的受控内部 API
|
||
→ 8核32G 做权限、额度、日志、落库
|
||
```
|
||
|
||
不要让 n8n 或 agent 变成"野生后台"。
|
||
|
||
### 2. Dify:第一阶段不部署
|
||
|
||
Dify 最低要求 CPU ≥ 2 Core、RAM ≥ 4 GiB(官方推荐 8 GiB 更稳)。4核4G 已有 Web 产品页 + Gitea + n8n + agent,再放 Dify 容易"能启动但卡、能用但不稳、一跑 workflow 就吃满"。
|
||
|
||
而且 Dify 和你自己的 AI Gateway / RAG Worker 有功能重叠,知习核心知识库才是优先事项。
|
||
|
||
**决策:**
|
||
|
||
```text
|
||
第一阶段不部署 Dify。
|
||
后续如需实验,放 8核32G sandbox profile(不连生产库)。
|
||
```
|
||
|
||
```bash
|
||
# 以后如需实验:
|
||
docker compose --profile dify up -d # 用完关掉
|
||
```
|
||
|
||
### 3. 轻量 agent:可以放
|
||
|
||
适合放 4核4G 的 agent 类型:
|
||
|
||
```text
|
||
营销内容生成 agent
|
||
定时调研 agent
|
||
Gitea issue 分析 agent
|
||
自动发布提醒 agent
|
||
数据采集辅助 agent
|
||
n8n workflow agent
|
||
小型 webhook agent
|
||
```
|
||
|
||
规则和 n8n 一样:**agent 可以调用知习 API,但不可直接连生产 MySQL、操作 Qdrant、拿 COS 主密钥。**
|
||
|
||
---
|
||
|
||
## 八、最终部署架构图 ✅ 已落实
|
||
|
||
```text
|
||
iOS / Web
|
||
↓
|
||
┌───────────────┴───────────────┐
|
||
│ │
|
||
┌───────┴──────────┐ ┌───────┴──────────┐
|
||
│ 8核32G CVM │ │ 4核4G 轻量云 │
|
||
│ (生产核心服务器) │ │ (工具/辅助服务器) │
|
||
│ │ │ │
|
||
│ ┌──────────────┐ │ │ ┌───────────────┐ │
|
||
│ │ gitea-runner │ │ CI/CD │ │ gitea-runner │ │
|
||
│ │ -prod │ │ │ │ -web │ │
|
||
│ └──────────────┘ │ │ └───────────────┘ │
|
||
│ ┌──────────────┐ │ │ ┌───────────────┐ │
|
||
│ │ NestJS API │ │ │ │ Web 产品页 │ │
|
||
│ └──────┬───────┘ │ │ │ (landing) │ │
|
||
│ │ │ │ └───────────────┘ │
|
||
│ ┌──────┴───────┐ │ │ ┌───────────────┐ │
|
||
│ │ MySQL │ │ 权威业务库 │ │ Gitea │ │
|
||
│ └──────────────┘ │ │ │ (主服务) │ │
|
||
│ ┌──────────────┐ │ │ └───────────────┘ │
|
||
│ │ Redis │ │ 队列/缓存 │ ┌───────────────┐ │
|
||
│ └──────────────┘ │ │ │ n8n │ │
|
||
│ ┌──────────────┐ │ │ └───────────────┘ │
|
||
│ │ Qdrant │ │ 向量索引 │ ┌───────────────┐ │
|
||
│ └──────────────┘ │ │ │ agent runner │ │
|
||
│ ┌──────────────┐ │ │ └───────────────┘ │
|
||
│ │ RAG Worker │ │ 解析/切片 │ ┌───────────────┐ │
|
||
│ └──────────────┘ │ │ │ Uptime Kuma │ │
|
||
│ ┌──────────────┐ │ │ └───────────────┘ │
|
||
│ │ AI Gateway │ │ AI 调度 │ │
|
||
│ └──────────────┘ │ │ (不承载正式 │
|
||
│ ┌──────────────┐ │ │ 业务数据) │
|
||
│ │ Backup+Cron │ │ 备份/清理 └───────────────────┘
|
||
│ └──────────────┘ │
|
||
│ │
|
||
│ /data (70G) │
|
||
└────────┬─────────┘
|
||
│
|
||
┌───────┴───────┐
|
||
│ 腾讯云 COS │
|
||
│ │
|
||
│ 原始文件 │
|
||
│ parsed.md │
|
||
│ OCR/Vision │
|
||
│ 备份快照 │
|
||
│ 用户头像 │
|
||
│ 导出文件 │
|
||
└───────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 九、CI/CD 部署流水线 ✅ api-server + web-projects 均已配置
|
||
|
||
### 1. 总原则
|
||
|
||
```text
|
||
Gitea 本体只放 4核4G,Runner 两台都装
|
||
服务跑在哪台服务器,Runner 就装在哪台服务器
|
||
每台 Runner 本地构建、本地部署,不跨服务器传输构建产物
|
||
```
|
||
|
||
不要搞成"4核 Runner 构建后端 → 传到 8核部署",多一层 SSH + 传输 + 1Mbps 带宽瓶颈。
|
||
|
||
### 2. Runner 分工
|
||
|
||
**4核4G:gitea-runner-web**
|
||
|
||
```text
|
||
标签:web, tools, staging, docker
|
||
负责:
|
||
Web 产品页部署
|
||
Gitea Webhook 自动化
|
||
n8n / 工具服务部署
|
||
轻量 agent 更新
|
||
```
|
||
|
||
**8核32G:gitea-runner-prod**
|
||
|
||
```text
|
||
标签:prod, backend, rag, docker
|
||
负责:
|
||
NestJS 后端部署
|
||
Prisma migration
|
||
MySQL / Redis / Qdrant docker compose 更新
|
||
RAG Worker 部署
|
||
AI Gateway 部署
|
||
备份脚本部署
|
||
```
|
||
|
||
### 3. Runner 安装 ✅ 已完成
|
||
|
||
- ✅ 8核32G: `gitea-runner` systemd 自启
|
||
- ✅ 4核4G: `gitea-runner` systemd 自启(单一 runner 同时处理 api-server 和 web-projects)
|
||
|
||
```bash
|
||
sudo useradd -m -s /bin/bash deploy
|
||
sudo usermod -aG docker deploy
|
||
```
|
||
|
||
8核上注册 runner 到 4核 Gitea:
|
||
|
||
```bash
|
||
# 在 8核32G 上执行
|
||
./gitea-actions-runner register \
|
||
--name zhixi-prod-runner \
|
||
--labels prod,backend,rag,docker \
|
||
--instance https://gitea.yourdomain.com \
|
||
--token <从 Gitea Admin 获取>
|
||
```
|
||
|
||
### 4. Workflow 实际部署 ✅ 已落地
|
||
|
||
**后端部署(4核4G runner 执行):**
|
||
- 实际文件:`/home/ubuntu/api-server/.gitea/workflows/deploy.yml`
|
||
- 流程:git pull → Docker build → 处理迁移卡死 → 启动 zhixi-api 容器 → 健康检查
|
||
|
||
**Web 部署(4核4G runner 执行):**
|
||
- 实际文件:`/tmp/web-projects/.gitea/workflows/deploy.yml`
|
||
- 流程:git clone/pull → Astro build (Docker node:22) → Nginx 配置 → 部署到 /var/www/longde.cloud → 确保后端运行 → Nginx reload
|
||
- 最后部署:2026-05-20 13:38 ✅
|
||
|
||
### 5. 密钥管理 ✅ 已配置
|
||
|
||
生产密钥已放在服务器本地:
|
||
|
||
```text
|
||
8核32G: /opt/zhixi/env/.env.production ✅ 全部必需密钥已配置
|
||
4核4G: /etc/zhixi/.env.production ✅(含 COS/DEEPSEEK/SILICONFLOW/JWT)
|
||
rag-worker: /opt/zhixi/backend/rag-worker/.env ✅
|
||
|
||
已配置:
|
||
DATABASE_URL ✅
|
||
REDIS_HOST/REDIS_PORT/REDIS_PASSWORD ✅
|
||
QDRANT_URL ✅
|
||
COS_SECRET_ID / COS_SECRET_KEY ✅
|
||
DEEPSEEK_API_KEY ✅
|
||
SILICONFLOW_API_KEY ✅
|
||
JWT_SECRET ✅
|
||
RAG_WORKER_SECRET ✅
|
||
BAIDU_OCR_KEY ❌ 待开通
|
||
```
|
||
|
||
### 6. Gitea 挂了不影响生产 ✅ 已验证
|
||
|
||
```text
|
||
Gitea 只影响代码仓库和部署流水线
|
||
8核上的后端、MySQL、Redis、Qdrant 继续运行
|
||
最多暂时不能自动部署新版本
|
||
```
|
||
|
||
---
|
||
|
||
## 十、迁移执行计划 🔶 部分完成
|
||
|
||
因为现在数据库基本空,迁移很简单,按此顺序推进:
|
||
|
||
### 第一步:8核32G 基础环境 ✅ 已完成
|
||
|
||
```text
|
||
1. 挂载 /data 数据盘 ✅
|
||
2. 安装 Docker / Docker Compose ✅
|
||
3. 配置 Docker data-root → /data/docker ✅
|
||
4. 创建所有 /data 子目录 ✅
|
||
5. 创建 deploy 用户(用于 Runner 和部署)✅
|
||
```
|
||
|
||
### 第二步:部署核心服务 ✅ 已完成
|
||
|
||
```text
|
||
6. 部署 MySQL → /data/mysql,创建数据库 zhixi_prod ✅
|
||
7. 部署 Redis → /data/redis ✅
|
||
8. 部署 Qdrant → /data/qdrant,创建 collection zhixi_chunks ✅
|
||
9. 配置数据库连接:DATABASE_URL / REDIS_URL / QDRANT_URL ✅
|
||
```
|
||
|
||
### 第三步:数据库迁移 ✅ 已完成
|
||
|
||
```text
|
||
9. 修改 Prisma schema:BigInt → String(cuid) ✅
|
||
10. 初始化空库 migration ✅ (3 个 migration 执行)
|
||
11. 4核4G mysqldump → 导入 8核32G ✅
|
||
12. 配置备份脚本(MySQL + Qdrant + 同步 COS)🔶 本地完成,COS 同步待配
|
||
```
|
||
|
||
### 第四步:CI/CD 搭建 ✅ 已完成
|
||
|
||
```text
|
||
14. 8核32G 安装 gitea-runner-prod ✅
|
||
15. 4核4G 安装 gitea-runner-web ✅ (单一 runner 覆盖两端)
|
||
16. 配置 Gitea Secrets ✅
|
||
17. 编写 deploy-backend.yml / deploy-web.yml ✅
|
||
18. 测试 push → 自动构建 → 自动部署流水线 ✅ (web 今日 13:38 部署成功)
|
||
```
|
||
|
||
### 第五步:DNS 与后端切换 ✅ 已完成
|
||
|
||
```text
|
||
19. 确认 8核32G 上 NestJS 正常运行 ✅
|
||
20. DNS api.longde.cloud 切换到 8核32G ✅
|
||
21. Nginx 配置 SSL 证书 ✅ (Let's Encrypt)
|
||
22. 修改 DATABASE_URL 指向新 MySQL ✅
|
||
23. 测试 iOS 登录功能(通过域名 + HTTPS)✅
|
||
```
|
||
|
||
> **当前状态:DNS 已切换到 8核32G。✅**
|
||
|
||
### 第六步:知识库开发 ✅ 核心已通
|
||
|
||
```text
|
||
23. 在 8核32G 上按知识库设计文档建表 ✅ (35 张表)
|
||
24. 实现文件上传 → COS 🔶 (COS 凭据已配,API 已就,待 iOS 真文件测试)
|
||
25. 部署 RAG Worker ✅ (systemd zhixi-worker 已启动)
|
||
26. 打通索引流程 → 学习流程 ✅
|
||
- raw text 导入全链路 ✅ (chunk→embed→Qdrant→candidate)
|
||
- RAG 对话 ✅ (检索→rerank→DeepSeek+citations)
|
||
- 多轮对话 ✅ (history 参数)
|
||
- 级联删除 ✅
|
||
- 备份 ✅ (本地 cron,COS 同步待配)
|
||
- 学习引擎(ActiveRecall/AIAnalysis/FocusItem/Review)模块已建,待端到端对接测试
|
||
```
|
||
|
||
|
||
---
|
||
|
||
## 十一、最终拍板清单(执行状态)
|
||
|
||
```text
|
||
# 存储架构
|
||
1. ✅ 唯一权威 MySQL 放 8核32G,4核4G 不再建新表
|
||
2. ✅ ID 类型立即从 BigInt 改为 String(cuid),趁库空
|
||
3. ✅ Redis 放 8核32G(队列 / 缓存 / 限流 / 锁)
|
||
4. ✅ Qdrant 放 8核32G(向量索引)
|
||
5. ✅ COS 继续作为文件 + 备份存储
|
||
6. ✅ 不引入 MongoDB / Elasticsearch / ClickHouse
|
||
|
||
# 8核32G:生产核心服务器
|
||
7. ✅ 全量承载 NestJS + MySQL + Redis + Qdrant + RAG Worker + AI Gateway
|
||
8. ✅ 负责全部用户数据、知识库、学习引擎、成本记录、后台审计
|
||
9. ✅ 安装 gitea-runner-prod(负责后端/知识库/RAG 部署)
|
||
|
||
# 4核4G:工具服务器 / 辅助服务器
|
||
10. ✅ 保留 Gitea 主服务 + Web 产品页
|
||
11. ✅ 安装 gitea-runner-web(单一 runner 覆盖 web + api-server 两端)
|
||
12. ⏳ 可以加 n8n(营销自动化、Webhook、流程编排)
|
||
13. ⏳ 可以加轻量 agent runner(不直接操作生产库)
|
||
14. ⏳ 可以加 Uptime Kuma 监控
|
||
15. ✅ Dify 第一阶段不部署
|
||
16. ✅ 不承载正式 MySQL / Qdrant / Redis / RAG Worker
|
||
|
||
# CI/CD
|
||
17. ✅ Gitea 本体只放 4核4G,Runner 两台都装
|
||
18. ✅ 服务跑在哪台服务器,Runner 就装在哪台服务器
|
||
19. ✅ 生产密钥放服务器本地 .env,不写入仓库
|
||
20. ✅ Runner 使用 ubuntu 用户
|
||
|
||
# 安全边界
|
||
21. ⏳ n8n / agent 调用知习受控 API,不直连生产库(n8n 未部署)
|
||
22. ✅ 迁移完成后 4核4G 旧 API 容器已移除
|
||
23. ✅ UFW 防火墙两台均已启用(22/80/443 + 4核4G 2222)
|
||
24. ✅ Fail2ban 4核4G 已安装(sshd jail)
|
||
```
|
||
|
||
后续不会再有一次大的数据库迁移。
|
||
|
||
---
|
||
|
||
## 十二、仍存缺陷与待决策项(状态更新)
|
||
|
||
以下是当前方案中尚未覆盖或需要你拍板的点,按风险等级排序。
|
||
|
||
### 🔴 高风险(上线前必须定)
|
||
|
||
| # | 问题 | 现状 | 建议 |
|
||
|---|------|------|------|
|
||
| 1 | **3Mbps 公网带宽** | ✅ 已处理 | 日常增量文件(单文件 ≤20MB)影响可控。大文件下载 COS + 备份上传走后台队列异步处理,不阻塞 API。 |
|
||
| 2 | **Qdrant 无内置认证** | ✅ 已定 | 仅绑定 `127.0.0.1:6333`,不公网暴露。 |
|
||
| 3 | **HTTPS 证书** | ✅ 已配置 | Let's Encrypt 已生效,api.longde.cloud + longde.cloud + git.longde.cloud |
|
||
| 4 | **MySQL 配置调优** | ✅ 已应用 | `innodb_buffer_pool_size=8G`,`max_connections=100` |
|
||
|
||
### 🟡 中风险(迁移前应定)
|
||
|
||
| # | 问题 | 现状 | 建议 |
|
||
|---|------|------|------|
|
||
| 5 | **Redis 持久化** | ✅ 已配置 | AOF everysec + RDB 双开 |
|
||
| 6 | **Docker 容器网络规划** | ✅ 已配置 | `zhixi-net` bridge 网络,MySQL/Redis 绑定 localhost |
|
||
| 7 | **日志轮转与保留** | 🔶 /data/logs 目录已建 | logrotate 待确认 |
|
||
| 8 | **健康检查端点** | ✅ 已实现 | `/api` 返回 `{"status":"ok"}`,被 CI/CD 使用 |
|
||
| 9 | **两服务器间通信** | ✅ 内网直连 | 双向 ~1.9ms,Runner/API 互调均走内网 |
|
||
| 10 | **COS 带宽成本** | ✅ 已验证 | Bucket `zhixi-1259685406`,同区 VPC 内网免流量费 |
|
||
|
||
### 🟢 低风险(后续迭代时再定)
|
||
|
||
| # | 问题 | 现状 |
|
||
|---|------|------|
|
||
| 11 | **API 版本管理** | ⏳ 无 /api/v1/ 前缀 |
|
||
| 12 | **灰度/蓝绿部署** | ⏳ 后续 |
|
||
| 13 | **数据库读写分离** | ⏳ 后续 |
|
||
| 14 | **异地备份(COS 同步)** | ⏳ 本地备份已有,COS 上传待配 |
|
||
| 15 | **4核4G 最终去留** | ✅ 保留作为工具服务器 |
|
||
| 16 | **Docker Compose 统一** | 🔶 当前独立 docker run,未统一 compose |
|
||
| 17 | **logrotate** | ⏳ 待确认 |
|
||
| 18 | **BAIDU_OCR_KEY** | ✅ 已开通(AppID 7767914) |
|
||
|
||
---
|
||
|
||
## 十三、当前工作流总览(2026-05-20 终态)
|
||
|
||
### 已实现并验证的流程
|
||
|
||
**流程一:文档导入(NestJS BullMQ Worker)**
|
||
```
|
||
POST /api/imports {rawText, knowledgeBaseId}
|
||
→ DocumentImportWorker:
|
||
→ ChunkingService(512t/64overlap,按标题/段落/句子分割)
|
||
→ VectorService(bge-m3 batch 50 → Qdrant UUID upsert → MySQL chunk 写入)
|
||
→ KnowledgeImportWorkflow(DeepSeek 提取知识点)
|
||
→ ImportCandidate 写入
|
||
→ KB.itemCount 更新
|
||
→ COMPLETED
|
||
```
|
||
|
||
**流程二:RAG 对话**
|
||
```
|
||
POST /api/rag/chat {knowledgeBaseId, query, history?}
|
||
→ RagChatService:
|
||
→ embed query(bge-m3)
|
||
→ Qdrant 向量搜索(按 kbId/deleted 过滤)
|
||
→ rerank(bge-reranker-v2-m3)
|
||
→ DeepSeek 回答 + citations
|
||
→ 支持多轮(history 参数,最近 10 条上下文注入)
|
||
```
|
||
|
||
**流程三:知识库管理**
|
||
```
|
||
POST /api/knowledge-bases 创建
|
||
GET /api/knowledge-bases 列表
|
||
GET /api/knowledge-bases/:id 详情
|
||
PATCH /api/knowledge-bases/:id 更新
|
||
DELETE /api/knowledge-bases/:id 级联删除(items/chunks/candidates/imports/sources/Qdrant)
|
||
```
|
||
|
||
**流程四:备份**
|
||
```
|
||
cron 0 3 * * * /opt/zhixi/backup/backup.sh
|
||
→ MySQL dump + Qdrant snapshot → /data/backups/
|
||
→ 本地保留 7 天 + 物理清理(cron 0 4)
|
||
```
|
||
|
||
### 已建但未端到端对接的模块
|
||
|
||
| 模块 | 状态 | 缺什么 |
|
||
|------|------|--------|
|
||
| ActiveRecall | controller + worker | 与学习 session 的串联未测试 |
|
||
| AIAnalysis | controller + AiAnalysisWorker + 2 workflows | 同上 |
|
||
| FocusItem | controller + service | 依赖 AIAnalysis 输出 |
|
||
| ReviewCard | controller + workflow | 依赖 FocusItem 触发 |
|
||
| LearningSession | controller + service | 独立可用,缺学习引擎串联 |
|
||
| LearningActivity | heatmap/summary/trend | 数据写入了但从未被查询展示 |
|
||
| Files/COS 上传 | controller + COS SDK | 待 iOS 端真文件触发测试 |
|
||
|
||
### 待完成(代码级)
|
||
|
||
| # | 事项 | 说明 |
|
||
|---|------|------|
|
||
| 1 | COS 备份同步 | 每日备份后上传到 COS |
|
||
| 2 | COS 生命周期 | 7 天物理删除策略 |
|
||
| 3 | MySQL 物理清理 | 30 天 deletedAt 清理脚本 |
|
||
| 4 | Docker Compose 统一 | 整理 docker run 为 compose |
|
||
| 5 | logrotate 确认 | 检查轮转配置 |
|
||
|
||
### 待完成(产品/策略级)
|
||
|
||
| # | 事项 | 说明 |
|
||
|---|------|------|
|
||
| 6 | 学习引擎串联测试 | ActiveRecall→AIAnalysis→FocusItem→ReviewCard |
|
||
| 7 | iOS 文件上传测试 | COS 真文件上传 + Python Worker 解析 |
|
||
| 8 | Chat session 持久化 | 服务端存储 session + messages |
|
||
| 9 | 知识库设计文档决策表 21/23/24 | COS 同步 + 物理清理 |
|
||
|
||
---
|
||
|
||
## 十三、文档关联索引
|
||
|
||
本文档应与其他设计文档配合使用:
|
||
|
||
```text
|
||
知识库设计.MD → 数据模型、API 设计、RAG 流程、额度系统
|
||
服务器与数据库部署方案.MD → 本文档:服务器分工、存储架构、CI/CD
|
||
(后续)Prisma Schema → 具体表结构实现
|
||
(后续)docker-compose.yml → 容器编排配置
|
||
```
|
||
|