读写分离落地要注意什么?主从延迟导致的“读旧数据”怎么破?
结论先行:读写分离把读流量打到从库以扩展读能力,但会引入“刚写完就读到旧数据”的延迟问题。落地的三条底线:事务内必须走主库、一致性要求高的读强制主库、写后立即读做延迟兜底;判断一个读请求能否走从库,先看它能容忍多长的延迟窗口。
一、读写怎么分
- 中间件层:ShardingSphere、MyCat 等对应用透明路由,维护成本集中在中间件。
- 应用层:数据源路由,写走主库、读走从库,按注解或上下文切换。
- 监控维度:主从延迟、从库负载、读写占比都要有指标,否则切流就是盲切。
写请求 / 事务 ----------------> 主库
读请求(可容忍延迟)----------> 从库集群
读请求(强一致场景)----------> 强制主库
二、绕不开的问题清单
| 问题 | 典型场景 | 对策 |
|---|---|---|
| 延迟读旧数据 | 下单成功跳转订单页 | 强制主库 / 半同步 / 等位点 |
| 事务内读从库 | 事务里再查刚写的行 | 事务内一律走主库 |
| 从库被打挂 | 从库读请求堆积 | 从库限流、读比例监控 |
| 主库单点 | 主库故障全线不可写 | 半同步 + 主从切换 + 探活 |
| 数据不一致 | 从库重放中断 | 监控 Slave_SQL_Running 与延迟 |
三、强一致读的三种兜底
- 强制主库:该接口直接路由主库,简单粗暴,只给高频敏感接口用。
- 半同步复制:提交时至少一个从库确认收到 binlog,缩短暴露窗口。
- 等位点读:客户端记录写后的 binlog 位点,从库追到位点才响应(实现成本高)。
- 演进顺序:先强制主库 + 半同步把窗口压小,确有收益再评估等位点读的复杂度。
四、落地检查清单
- 事务内读与强一致读是否都强制主库?
- 从库延迟与两个线程状态是否有监控告警?
- 主库故障时切换演练是否定期执行?
常见追问与记忆点
- 追问:读写分离能解决主库写入瓶颈吗?不能,它只扩展读;写压力要靠分库分表与缓存吸收。
- 追问:从库读挂了怎么办?探活摘除并告警,短时把流量切回主库或其它从库。
- 记忆点:读写分离是读扩展而非写扩展;事务内走主库,敏感读强制主库或做延迟兜底。