读写分离
写主读从、延迟与路由。
30 分钟
读写分离
主库扛写入,从库分担读请求——读写分离 是复制拓扑最常见的用法。它能显著扩展读能力,但引入 复制延迟 与 路由复杂度。本课衔接 scale-replication 与 postgresql-essentials,落实 building-for-scale 的读路径拆分。
学习目标
- 设计写主读从的路由规则与数据源切换方式
- 处理「写后读」一致性:读己之写、延迟感知路由
- 评估何时读写分离不够,必须上分片
核心概念
写 / 强一致读 → Primary
普通读 → Replica-1, Replica-2(轮询 / 随机)
| 挑战 | 现象 | 缓解 |
|---|---|---|
| 复制延迟 | 刚注册却查不到用户 | 写后短暂读主 / 带版本校验 |
| 事务读 | 同一事务内读从库不一致 | 事务内强制走主 |
| 从库故障 | 读流量集中剩余从库 | 健康检查 + 自动剔除 |
Spring 实现路径:
- 动态数据源
@RoutingDataSource+@Transactional(readOnly=true)路由从库 - ShardingSphere / MyCat 等中间件透明读写分离
- MyBatis 多
SqlSessionFactory显式分离
// 伪代码:注册后 2 秒内读主
if (withinWriteWindow(userId)) routeToPrimary();
else routeToReplica();
何时不够:写 QPS 也到顶、单表过大——需 scale-sharding。读极热走 scale-cache。
与 ORM
orm-essentials 中注意:只读事务 + lazy load 仍可能打到从库,写操作后的同一请求线程应绑主库。
练习
- 列出系统中哪些读 API 可接受 1 秒延迟、哪些必须强一致
- 实现或画出
@ReadOnly注解 + 路由拦截器流程 - 压测:从库延迟 500ms 时,用户侧会出现哪些 bug 场景
小结
读写分离cheap 地扩展读——路由写清楚、写后读处理掉,别让用户看见「刚提交的数据不见了」。
加载本节练习…