复制:同步异步、主从与故障切换

kp-023 · 分布式与NoSQL进阶约 25 分钟已校对

前置知识点

前置:

相关知识点

相关:

学习进度:

一句话定义

复制(Replication)把同一份数据维持在多个节点:主库处理写并把变更日志流式发给从库,按从库确认时机分为同步、半同步与异步三种模式,换来的是读扩展、地理就近与容灾冗余。

为什么重要

前置知识

kp-014(事务与日志)、建议先浏览 kp-020(日志是复制的载体)。

核心概念

原理与机制

从库重放主库日志流实现最终收敛。三种模式给出「性能-安全」滑杆:异步零等待但主库宕机可能丢最近事务;同步零丢失但任一从库故障即阻塞写入;半同步用「一个 ACK」把丢失窗口压缩到「主从同时宕机」这一小概率。读扩展的经典陷阱是写后读(Read-your-writes):用户写主库后立刻读从库可能读到旧值,工程对策包括会话粘滞(该用户短窗口内读主)、位点校验(比较 GTW/LSN 足够新才读从)、时间戳令牌。故障切换的核心难题是「如何确认主库真死了且不会复活」:租约超时 + 防腐化(fencing token,用单调递增的纪元号拒绝旧主写入)是标准答案;没有 fencing 的切换脚本在分区场景必然脑裂。多主拓扑带来冲突写,需要按最后写胜出(LWW)、或冲突-free 数据类型(CRDT)收敛,复杂度陡增。

实例或案例

读写分离部署:1 主 2 异步从,报表与列表查询走从库,下单写主库。一次机房网络抖动使从库延迟到 8 秒:用户支付成功页跳转后订单列表却「消失」,客服工单暴增。修复方案:支付成功后的 30 秒内该用户请求强制读主 + 从库延迟超阈值自动摘除读流量——这是「写后读一致性」的教科书治理。半同步改造后(等待至少 1 从 ACK),主库整机故障实现零丢失切换,代价是写延迟增加一个机房 RTT。

常见误区

自测题

  1. 半同步复制在什么极端场景仍可能丢数据? 答:主库与被 ACK 的从库同时永久损坏(或 ACK 前日志未落从盘),此时没有任何节点持有该事务。
  2. 什么是 fencing token,解决什么问题? 答:故障切换时由协调方颁发的单调递增纪元号,存储层拒绝携带旧纪元号的写入,防止旧主「复活」后造成脑裂写冲突。

公式或模型

一致性窗口 ≈ 复制延迟 lag;写后读不一致概率 ≈ lag / 读间隔(间隔小于 lag 的读都可能踩空)。可用性权衡:同步复制可用性 = 全体副本可用性之积(任一故障即不可写)。

图示

主库(写) 从库 1(读) 从库 2(读) 日志流(异步重放) lag = 落后位点 同步:等 ACK | 半同步:等 1 个 ACK | 异步:不等
复制拓扑:模式差异只在「主库是否等待从库确认」这一步

直观类比

异步复制像群发消息后不等回音就继续开会:快,但有人根本没收到;半同步像点名确认「至少一个人收到」;完全同步像全员签到才继续——最稳也最容易被一个人卡住全场。

与其他知识点的关系

kp-020 的日志流是复制的原料;kp-026 用共识协议把「手动切换 + fencing」升级为自动化安全选主;kp-025 给复制模式与一致性、可用性的理论边界。

延伸阅读