ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数据库读写分离与主从延迟治理复盘:刚写入就读不到、读到旧数据、路由错表的生产级方案

数据库读写分离与主从延迟治理复盘:刚写入就读不到、读到旧数据、路由错表的生产级方案 随着业务增长单库 CPU、连接数被读请求占满把读压力分流到多个从库的读写分离成了标配。理论上主库写、从库读既能分担压力又能提升读性能。但上线后用户最常投诉的是刚下单完跳转到列表页订单不见了支付完刷新页面状态还是待支付或者某些查询莫名其妙连到了主库拖慢了写。这些问题的根源不是读写分离不好用而是主从复制本身有延迟、路由策略没区分业务场景。主库写入后数据要经过复制才能到从库这段时间差内读从库就读到旧数据。本文讲清楚主从延迟从哪来、怎么识别和治理、哪些读必须走主库。一、读写分离高频踩坑场景1. 主从延迟刚写完就读到旧数据主库提交事务后binlog 要传到从库、重放后才能查到。正常情况下延迟可能是毫秒到秒级但大事务、批量更新、网络抖动时延迟可能拉到几秒甚至更久。用户写后立刻读的请求被路由到从库就读到了旧数据表现为数据丢失。2. 大事务与批量更新放大延迟一次性批量更新大量数据、跑长事务会堵住从库的重放线程导致后续所有写入都延迟所有读从库的请求都读到旧数据。这类问题在夜间批处理、数据订正时最容易发生。3. 路由策略粗暴读请求乱走不区分业务一律把 SELECT 打从库把写后读、强一致读也分到从库或者事务内的读请求因为连接没绑定主库而跑到从库导致同一个事务里前后读到不一致数据。4. 主库故障切换后连接没切回来主库宕机提升从库为新主库后应用侧的数据源、读写路由没自动更新或者旧连接还指向旧主导致写失败、读乱路由。高可用切换没有和应用侧联动等于高可用没闭环。二、主从延迟的识别与监控1. 持续监控从库延迟把主从延迟Seconds_Behind_Master 或对应指标作为核心监控项设置阈值告警。延迟超过业务可接受范围时要有应对手段而不是等用户投诉才发现。SHOW REPLICA STATUS\G -- 重点关注 -- Seconds_Behind_Source从库延迟秒数 -- Replica_IO_Running / Replica_SQL_Running复制线程是否正常2. 定位延迟来源延迟高时先看是不是大事务、批量更新堵住了重放再看从库自身性能IO、CPU、磁盘是否扛不住网络带宽不足也会让 binlog 传输变慢。对症下药而不是盲目加从库。3. 避免大事务把大批量更新拆成小批次、小事务执行避免单个事务长时间占用从库重放核心业务的关键写操作避开与批处理同时进行减少延迟峰值。三、读请求路由策略1. 写后读强制走主库对于刚写完就要读的场景下单后看订单、支付后看状态必须在一段时间内强制走主库或由业务层判断该请求是否属于写后读直接路由主库避免读到旧数据。Transactional public void placeOrder(OrderRequest req) { orderMapper.insert(req); // 标记后续读请求强制走主库 DbContext.forceMaster(); } // 查询时判断若本线程标记走主库则路由主库 public Order queryOrder(Long orderId) { if (DbContext.isForceMaster()) { return masterDao.selectById(orderId); } return slaveDao.selectById(orderId); }2. 事务内读走主库一个事务里的多次读必须在同一个数据源、且保证读到自己刚写的数据因此事务内的读应路由主库避免跨库、跨主从不一致。3. 按业务一致性要求分级强一致、写后读、事务内读走主库普通列表、报表、搜索等可容忍短暂延迟的读走从库。不要一刀切全部走从库按业务对一致性的真实要求分级路由。四、从库选型与高可用切换1. 从库按读负载分担多个从库之间做负载均衡把读请求均匀分散报表、后台查询这类重读负载尽量用独立从库避免和在线业务读争抢资源。2. 故障切换与应用联动主从高可用切换时应用侧要能感知新主库地址通过配置中心、服务发现或数据库代理自动更新数据源避免切换后应用仍指向旧主。数据库代理层如统一中间件能屏蔽主从拓扑变化减少应用侧改造。3. 定期演练主从切换主从切换流程要定期演练确认应用数据源能正确切到新主、写不中断、读路由正常真正故障发生时才不会手忙脚乱。五、总结读写分离带来的读到旧数据问题本质是主从复制延迟和路由策略共同造成的。核心可以归纳为持续监控主从延迟并设置告警用小事务、分批更新避免大事务堵重放写后读、事务内读强制走主库普通读才走从库多从库分担读负载重读用独立从库主从切换要和应用数据源联动并定期演练。读写分离不是配好主从就完事把延迟治理和路由分级做好才能既分担压力又不让用户读到旧数据。
返回列表