基础设施选型指南:SQLite / MySQL / PostgreSQL / Redis / Tengine(Nginx)
🎯 本篇目标:回答一个新手最常见的困惑——"我的项目什么时候需要引入这些组件?"
原则先行:不为简历堆技术,只为解决实际问题。每个组件都从"没有它会出什么问题"讲起,并标注它在 会员管理系统 演进路线中的位置。
1. 全景图:各组件的职责边界
用户请求
│
▼
┌─────────────┐ ┌──────────────────────────────────┐
│ Tengine │ │ FastAPI 应用 │
│ (Nginx 系) │────▶│ ├─ 业务逻辑 │
│ 反向代理 │ │ ├─ 需要缓存/计数? ──────▶ Redis │
│ TLS/静态/限流│ │ └─ 需要持久化数据? ──▶ PostgreSQL│
└─────────────┘ └──────────────────────────────────┘
(MySQL 和 PostgreSQL 二选一)
| 组件 | 一句话定位 | 你不引入它的默认状态 |
|---|---|---|
| SQLite | 零配置单文件数据库 | uvicorn + 一个 .db 文件就能跑(会员系统现状) |
| PostgreSQL | 功能最强的开源关系库,默认首选 | 数据还在 SQLite 里 |
| MySQL | 流行的开源关系库,生态成熟 | 同上 |
| Redis | 内存数据库:缓存/计数/分布式锁 | 每次都查库,全靠数据库扛 |
| Tengine(Nginx) | 反向代理服务器:TLS/静态/负载均衡 | uvicorn 裸奔对外,自己管 HTTPS |
💡 TS 对照
Node 世界的对应关系:SQLite ≈ 低配版 Prisma+SQLite;PostgreSQL/MySQL ≈ 你连过的各种云数据库;Redis ≈ Express 里的 ioredis(session/缓存);Nginx ≈ 你部署 Node 应用时前面挡的那层(如果你用过宝塔,网站"反代"功能就是 Nginx)。
2. SQLite:起点,也是被低估的狠角色
什么时候用
- ✅ 开发/测试环境(会员系统 P1-P5 全程)
- ✅ 单机部署、写入 QPS < 100 的小系统(内部工具、个人项目、博客后台)
- ✅ 嵌入式/本地应用(手机 App、桌面软件)
- ✅ 大量读多写少的边缘场景(甚至一些生产站点就用 SQLite)
什么时候必须离开
| 信号 | 原因 |
|---|---|
| 多实例部署 | SQLite 是单文件,多台机器不能共享同一文件 |
| 并发写入频繁 | 整库一把写锁,database is locked 会反复出现 |
需要 SELECT FOR UPDATE 语义验证 | 它的行锁语义和 PG/MySQL 不完全一致,测了也白测 |
💡 一个常见误区
"SQLite 不能生产使用"是过时结论。单机小系统它完全够格——真正让你换库的信号是多实例部署和并发写,而不是"上线"本身。
3. PostgreSQL vs MySQL:怎么选?
结论先行
没有明确理由时,选 PostgreSQL。 新项目 2024 年后的社区默认答案。
对比表
| 维度 | PostgreSQL | MySQL |
|---|---|---|
| 定位 | "功能的完全体",学术严谨 | "够用且快",互联网公司存量霸主 |
| JSON 支持 | jsonb 类型可索引可查询(强项) | JSON 类型存在但查询能力弱 |
| 复杂查询 | 窗口函数/CTE/全文检索/数组类型都强 | 简单查询性能优秀,复杂查询较弱 |
| 并发控制 | MVCC 实现更完善,FOR UPDATE SKIP LOCKED 等高级特性 | 常用特性都有 |
| 生态现状 | PostGIS(地理)、pgvector(AI 向量检索)等扩展是杀手锏 | 国内云厂商支持最广,DBA 好招 |
| 公司存量 | 新创公司/外企主流 | 国内大厂存量系统多 |
什么时候选 MySQL(真实理由,不是玄学)
- 团队/公司已有 MySQL 运维经验和监控体系
- 目标公司技术栈是 MySQL,为求职对齐
- 用阿里云 RDS 等,两个都支持 → 回到默认:选 PG
💡 和你 AI 学习路线的强关联
pgvector 是 Month 2 RAG 的隐藏考点:向量数据直接存 PostgreSQL 就能做小规模语义检索,不用单独部署 Milvus/Chroma。选 PG 等于给 AI 铺路。
引入时机(会员系统)
- P1-P5:SQLite 够用
- 演进步骤 ⑤(SaaS 化):换 PostgreSQL——因为多租户后需要真行锁 + pgvector + 更强的并发
4. Redis:什么时候才真的需要它?
判断标准:先问"数据库扛不住了吗?",再问"这个数据适合放内存吗?"
| 场景 | 用 Redis 吗 | 说明 |
|---|---|---|
| 缓存热点查询(套餐列表、行情价格) | ✅ 经典场景 | 读多写少 + 能容忍短暂不一致 |
| 登录限流(同 IP 5 次/分钟) | ✅ 计数器 INCR + EXPIRE | 会员系统 P2 的限流,单机可以用内存 dict,多实例必须 Redis |
| JWT 注销黑名单 | ✅ 带 TTL 的 key | token 剩余有效期 = TTL,自动过期清理 |
| 幂等键存储 | ✅ 天然适合 | SET idem:key value NX EX 86400 |
| 分布式锁(防并发下单) | ⚠️ 可以但慎重 | 优先用数据库行锁(P4 教的 FOR UPDATE),锁的语义更可靠 |
| Session 存储 | ⚠️ 有 JWT 就不需要 | 双 token 方案下无服务端 session |
| 消息队列 | ⚠️ 轻量场景用 Stream | 重度任务队列以后学 RabbitMQ/Kafka |
引入信号(满足任一)
- 多实例部署:限流/黑名单/幂等键存在"进程内存"里时,实例之间不共享 → 必须 Redis
- 数据库出现可观测的读压力:慢查询日志出现高频重复 SELECT
- 需要 TTL 语义的数据(验证码、防重放 nonce)
反模式(新手最容易犯)
# ❌ 反例:什么都往 Redis 塞,数据库成了"归档库"
# 会员档案、订单流水这种强一致、要关联查询的数据 → 永远在关系库
# Redis 只放"丢了也不心疼/能重建"的数据
cache.set(f"plan:{plan_id}", plan, ex=300) # ✅ 5 分钟缓存,过期回源
💡 会员系统里的 Redis 位置
文档 §5 安全清单里的"注销黑名单"和 §4.3 的幂等键,单机版用 SQLite 表实现即可;演进步骤④(多实例)时迁到 Redis,接口不用变——这就是 service 层封装的价值。
5. Tengine(Nginx):uvicorn 前面为什么必须挡一层?
先说清楚关系:Tengine 是阿里巴巴基于 Nginx 的分支,用法心智完全一致。uvicorn 是应用服务器,不是为直接暴露公网设计的。
Nginx/Tengine 承担的四件事
| 职责 | 没有它会怎样 |
|---|---|
| TLS 终结(HTTPS 证书) | uvicorn 自己配证书很别扭,且证书续期要重启应用 |
| 静态文件(Swagger、未来前端 dist) | 让 Python 进程送静态文件 = 浪费(Node 圈同理:不用 express 送 build 产物) |
| 反向代理 + 负载均衡 | proxy_pass http://127.0.0.1:8000;未来多实例 upstream 轮询 |
| 安全缓冲 | 隐藏后端细节、限速、大请求体拦截、超时控制 |
最小可用配置(会员系统部署用)
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;
# 限流:商业标准的登录保护(配合应用内 slowapi)
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr; # ★ 审计日志记录真实 IP
proxy_set_header X-Request-ID $request_id; # ★ 链路追踪贯穿全链路
proxy_read_timeout 60s;
}
location /docs { deny all; } # prod 禁 Swagger
}
💡 引入信号
第一个公网用户出现的那天。开发期 localhost 直连 uvicorn 没问题;上线 = uvicorn 只绑 127.0.0.1,Nginx 对外。这是商业部署的铁律(对照部署篇 Dockerfile 里 --host 0.0.0.0 是容器内、Nginx 在容器外的拓扑)。
6. "等"字辈:提前认识的其它成员
| 组件 | 解决什么问题 | 什么时候轮到它 |
|---|---|---|
| Elasticsearch | 全文搜索、复杂多条件检索 | 会员搜索从"LIKE 模糊查"进化到"分词/拼音/多字段权重"时。小规模 PG 全文检索可顶很久 |
| MongoDB | 文档模型、schema 灵活 | 数据结构真的不定型时(如 Agent 的对话轨迹快照)。别拿"不想建表"当理由 |
| RabbitMQ / Kafka | 异步任务、削峰、事件广播 | 发短信/生成报表不想阻塞接口时;Kafka 面向高吞吐日志流。起步用 FastAPI BackgroundTasks + Redis Stream |
| MinIO / OSS | 对象存储(文件) | 会员头像/合同扫描件。云上直接用 OSS/COS |
| Cron / Celery | 定时任务 | 到期提醒从"接口查"变成"每天 9 点主动推"时。轻量先 APScheduler |
💡 每个都遵循同一条铁律:先有痛,再引入。简历上写"用过"很容易被追问穿透,写"因为 X 问题引入 Y,解决了 Z"才立得住。
7. 决策速查卡(贴显示器系列)
需要存"必须不丢"的业务数据吗?
├─ 是 → 关系型数据库
│ ├─ 单机小系统起步 → SQLite
│ └─ 多实例/AI向量/复杂查询 → PostgreSQL(默认)
│ └─ 公司存量是 MySQL → MySQL
├─ 数据丢了能重建 + 读多写少/带过期时间?
│ └─ 是 → Redis
└─ 全文搜索/文件/异步任务?
→ 先用 PG/MinIO/BackgroundTasks 顶着,痛了再上专门组件
要暴露到公网吗?
└─ 是 → Nginx/Tengine 挡在 uvicorn 前面(TLS + 反代 + 限流)
8. 会员系统全演进路线(组件视角汇总)
| 阶段 | 组件变化 | 触发信号 |
|---|---|---|
| P1-P5(现在) | SQLite + uvicorn 裸跑 | — |
| 上线 v1 | + Tengine(Nginx) TLS/反代 | 第一个公网用户 |
| SaaS ①②③ | SQLite → PostgreSQL | 多实例部署 + pgvector 需求 |
| SaaS ④ | + Redis(黑名单/幂等键/限流迁过去) | 多实例内存不共享 |
| 成长期 | + Celery 定时任务、ES 搜索(视痛感) | 到期提醒要主动推送;搜索要分词 |
🔗 本篇与 Month 3 部署篇 的关系:部署篇教"怎么把容器跑起来",本篇教"跑起来之前每个组件该不该存在"。