读写分离

写请求路由到主库、读请求路由到从库,用复制扩展读吞吐;代价是复制延迟下的旧数据读,需要为“刚写就查”等场景保留走主库的路径。

读写分离是什么

读写分离把写请求路由到主库、读请求分流到从库(只读副本),用复制机制横向扩展读吞吐,同时让主库专注处理写入。代价是复制延迟带来的旧数据读:主库提交后从库要过一段时间才同步,用户「刚提交就查看」的场景最容易暴露问题。因此读写分离必须配套路由策略——哪些查询必须走主库、哪些可以接受秒级陈旧,以及延迟升高时如何自动收紧。

基本信息

适用场景读多写少、读可接受秒级陈旧、写集中在单库
复制方式异步复制延迟小但可能丢数据;半同步牺牲部分延迟换可靠性
路由依据按 SQL 类型、事务边界与会话状态判断
必备监控复制延迟(秒/字节)、从库负载与回放状态
故障处理从库不可用时降级为主库读或返回缓存,避免整站不可用

路由规则

场景路由目标注意点
普通查询从库可接受秒级延迟,注意读流量均匀分摊
写入后的读主库会话内保持读己之写,窗口与延迟监控联动
报表统计专用从库避免抢占在线读流量,限制并发与超时
事务内读主库必须读到本事务内的写入
强一致校验主库对账、余额校验等场景不走从库

典型使用场景

  • 读流量远大于写流量:用只读副本承接查询,主库专注写入
  • 报表与导出分流:把重查询放到专用从库,限制其资源占用
  • 异地读加速:就近读副本,减少跨地域访问延迟
  • 发布与维护窗口:主库切换期间从库继续提供只读服务
  • 灰度验证:先在只读副本上跑新查询,确认性能再上线
  • 扩容读能力:加副本比纵向升级主库更平缓

会话策略与降级

会话策略与降级
# 写后读主窗口:用户发生写操作后 N 秒内,该会话读请求强制走主库
# N 与复制延迟监控联动,延迟增大时自动放宽窗口
# 从库健康检查失败:临时摘除,读流量回到主库并记录降级事件
# 强一致标记:涉及金额与权限的读加 force_master 标记,绕过从库路由
# 观测:分别统计主库读与从库读的 QPS、延迟与降级次数
路由组件不能是单点:读写分离把请求集中到一个中间件上,它挂掉时读路径与写路径会同时不可用,必须有多实例与故障转移。
从库越多,一致性窗口越难保证:副本数量增加会让延迟分布变长,读己之写策略需要按最慢副本或按版本号校验,而不只看平均值。

易错点

  • 读流量固定走从库:用户刚提交订单就查不到,重复提交产生脏数据
  • 路由组件单点部署:故障时读写路径同时中断
  • 报表查询不加限制地跑在从库上:把在线读流量一起拖慢
  • 复制延迟不做监控:延迟数十秒也无感知,问题由业务方先发现
  • 事务内查询被路由到从库:读取过程需要主库临时表或未提交数据时报错

数据来源与参考

  • 《数据密集型应用系统设计》(Kleppmann)第 5 章
  • MySQL 8.0 Reference Manual:Replication
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌