主从延迟 3 秒导致读脏数据,如何在不改架构的前提下把延迟降到 500 ms 以内

解读

国内互联网面试中,主从延迟是 MySQL/Redis 等“读写分离”场景的高频考点。题干给出“3 s → 500 ms”且“不改架构”,意味着不能动“一主多从”这一基本拓扑,也不能加中间件做分片或改同步为半同步/强同步。面试官想考察的是:

  1. 能否快速把延迟量化并定位瓶颈(网络?IO?SQL?)
  2. 能否用“运维+内核+业务”组合拳,在既定硬件和版本下榨干最后一毫秒
  3. 是否具备“可灰度、可回滚、可验证”的意识,避免拍脑袋调参

知识点

  1. 延迟构成:T_delay = T_binlog_flush + T_network + T_sql_thread_relay + T_innodb_apply
  2. 监控指标:Seconds_Behind_Master、Relay_Log_Pos、Master_Log_File 差距、pt-heartbeat 真实延迟
  3. 并行复制:MySQL 5.6 库级、5.7 LOGICAL_CLOCK、8.0 WRITESET;slave_parallel_workers / slave_parallel_type
  4. 刷盘策略:sync_binlog、innodb_flush_log_at_trx_commit、slave_parallel_workers 与 group commit 的耦合
  5. 网络压缩:slave_compressed_protocol、binlog_transaction_compression
  6. 热点 SQL:大事务、无索引 DELETE/UPDATE、DDL 造成单 SQL 30 s+ 阻塞 SQL Thread
  7. 业务侧兜底:强制走主库注解、版本号 / 时间戳 二次校验、缓存围栏、延迟阈值开关
  8. 灰度验证:pt-heartbeat 持续打标,压测平台在 95th 延迟 < 500 ms 持续 30 min 方可上线

答案

“我会按‘监控→定位→治理→兜底’四步,在不动架构的前提下把延迟压到 500 ms 以内,并给出可量化的灰度方案。”

  1. 监控量化
    部署 pt-heartbeat 每 100 ms 打标,Grafana 看板区分“网络延迟”与“应用延迟”,确认 3 s 里 80% 来自 SQL Thread 慢,20% 来自网络。

  2. 内核层三板斧
    a) 并行复制:版本≥5.7 直接设 slave_parallel_type=LOGICAL_CLOCK、slave_parallel_workers=CPU 核数(物理机 32 核就 32),重启 slave 后 Seconds_Behind_Master 从 3 s 降到 600 ms。
    b) 刷盘降级:主库 innodb_flush_log_at_trx_commit=2、sync_binlog=1000(故障丢 1 s 数据,业务接受),从库 relay_log_recovery=1 保证安全;该步可再削 150 ms。
    c) 网络压缩:开启 slave_compressed_protocol,Binlog 压缩率 40%,跨机房 百兆带宽场景再降 80 ms。

  3. SQL 层止血
    用 pt-query-digest 抓 24 h 慢 SQL,发现 DELETE FROM log WHERE gmt_create<N 无索引,单事务 1.2 GB,SQL Thread 阻塞 2.1 s。加复合索引 (gmt_create, id) 并把大事务拆成 5000 行 / 次,延迟再降 900 ms。
    累计:3 s → 600 ms → 450 ms → 360 ms,已低于 500 ms 目标。

  4. 业务兜底(可回滚)
    在 DAO 层埋点:当 pt-heartbeat 延迟 > 500 ms 时,强制路由读请求到主库;延迟恢复后自动切回从库。开关放配置中心,10% 灰度→全量,回滚时间 < 30 s。

  5. 验收
    用 Gatling 模拟 2w 并发读、200 并发写,持续 30 min,95th 延迟 480 ms,错误率 0;出具报告并邮件同步 DBA、研发、测试三方,方可结项。

拓展思考

  1. 如果后续延迟要求 < 100 ms,而内核层已到极致,可考虑“半同步+无损半同步”或 MySQL Group Replication,但已超出“不改架构”前提,需提前与业务方评估写入可用性下降风险。
  2. 对 Redis 主从延迟,同理可用 replication backlog 调大、repl-disable-tcp-nodelay no、开启 psync2,但 Redis 瓶颈多在 RDB 重写时 fork 阻塞,需把 save 策略调松并开启 aof-use-rdb-preamble。
  3. 长期来看,建议把“延迟”纳入 SLA,与 QPS、RT 同等权重,每周出排行榜,让业务研发为自己的大事务买单,形成正向循环。