在不使用微服务的情况下扩展 PostgreSQL:来自 Notion 的 480 个分片的经验教训
发布: (2026年2月21日 GMT+8 14:03)
3 分钟阅读
原文: Dev.to
Source: Dev.to
TL;DR: Scaling Notion’s Monolith
- Application‑Level Sharding – 480 个逻辑分片映射到更少的物理节点。
- Shard Router – 使用 TypeScript 实现,利用
space_id % 480即时路由请求。 - PgBouncer – 充当流量控制器,池化连接以防止过载。
- Zero‑Downtime Migrations – “Shadow Write” 策略在保持应用在线的同时迁移数十亿行数据。
Chapter 1: The Problem with Monolith
在 Notion 的早期架构中,Node.js 后端配合单个 PostgreSQL 实例。随着时间推移,他们遇到了:
- CPU Saturation – 日常峰值经常超过 90 % 的利用率。
- The Vacuum Problem – Autovacuum 无法跟上,存在事务 ID 回绕的风险,回绕会为了保护数据完整性而停止写入。
Chapter 2: Why Not Microservices?
典型的微服务论点是“拆分代码,拆分负载”。Notion 走了一条不同的道路,保持单体代码库的同时对数据层进行扩展。
Chapter 3: The 480‑Shard Blueprint
Logical Shards
- Partition Key – 使用
space_id作为分区键,使得同一工作区的所有数据保持在一起,便于快速关联。 - Setup – 480 个独立的 schema(逻辑分片)分布在 32 台物理 AWS RDS 实例上。
Benefits
- 当某台服务器负载过高时,可以将一个逻辑 schema 移动到新服务器,实现线性可扩展性。
Chapter 4: The Great “Shadow” Migration
Backfill
- 将历史数据在后台迁移到新分片。
Double Writing
- 新的更改同时写入旧数据库和新分片。
Cutover
- 在比较引擎验证数据一致性后,将流量切换到新分片,实现零停机。
Future Improvements
- Scaling to 96 Nodes – 将物理节点数量扩展到 96 台,以进一步分散负载。
- Blocks All the Way Down – 继续把每一块内容都视为 block,实现细粒度分片。
- Data Lakes & Connection Hubs – 探索集中式分析和集成点。
Feel free to share your thoughts in the comments!