一句话定义
复制(Replication)把同一份数据维持在多个节点:主库处理写并把变更日志流式发给从库,按从库确认时机分为同步、半同步与异步三种模式,换来的是读扩展、地理就近与容灾冗余。
为什么重要
- 单机数据库的可用性上限就是主机可用性,复制是迈向高可用的第一步,也是 kp-024 分区与 kp-026 共识的地基。
- 复制延迟引发的「写后读不一致」(改了头像刷新又变回去)是最常见的分布式世界观冲击。
- 主从切换(Failover)的脑裂问题决定了「高可用方案」的真正成色。
前置知识
kp-014(事务与日志)、建议先浏览 kp-020(日志是复制的载体)。
核心概念
- 主库(Leader/Primary)/ 从库(Follower/Replica)。
- 同步复制:主库等待至少一个从库确认后提交;异步复制:本地提交即返回。
- 半同步(Semi-sync):等待一个 ACK 才返回,折中方案。
- 复制延迟(Replication Lag):从库落后主库的时间/位点差。
- 复制日志形态:逻辑日志(binlog 行格式、WAL 逻辑解码)与物理日志(页变更)。
- 故障切换:提升从库为主库;脑裂(两个主同时接受写)是最大风险。
- 多主(Multi-Leader)与无主(Dynamo 风格 Quorum)是另两种拓扑。
原理与机制
从库重放主库日志流实现最终收敛。三种模式给出「性能-安全」滑杆:异步零等待但主库宕机可能丢最近事务;同步零丢失但任一从库故障即阻塞写入;半同步用「一个 ACK」把丢失窗口压缩到「主从同时宕机」这一小概率。读扩展的经典陷阱是写后读(Read-your-writes):用户写主库后立刻读从库可能读到旧值,工程对策包括会话粘滞(该用户短窗口内读主)、位点校验(比较 GTW/LSN 足够新才读从)、时间戳令牌。故障切换的核心难题是「如何确认主库真死了且不会复活」:租约超时 + 防腐化(fencing token,用单调递增的纪元号拒绝旧主写入)是标准答案;没有 fencing 的切换脚本在分区场景必然脑裂。多主拓扑带来冲突写,需要按最后写胜出(LWW)、或冲突-free 数据类型(CRDT)收敛,复杂度陡增。
实例或案例
读写分离部署:1 主 2 异步从,报表与列表查询走从库,下单写主库。一次机房网络抖动使从库延迟到 8 秒:用户支付成功页跳转后订单列表却「消失」,客服工单暴增。修复方案:支付成功后的 30 秒内该用户请求强制读主 + 从库延迟超阈值自动摘除读流量——这是「写后读一致性」的教科书治理。半同步改造后(等待至少 1 从 ACK),主库整机故障实现零丢失切换,代价是写延迟增加一个机房 RTT。
常见误区
- 把异步复制当容灾备份:主库磁盘损坏时未发送的日志一同丢失,容灾必须配合备份(kp-031)。
- 用「从库延迟告警」代替写后读治理:告警只发现问题,业务侧仍需粘滞/位点策略兜底。
- 以为增加从库能提升写性能:写吞吐由主库单点决定,从库只扩展读能力。
自测题
- 半同步复制在什么极端场景仍可能丢数据? 答:主库与被 ACK 的从库同时永久损坏(或 ACK 前日志未落从盘),此时没有任何节点持有该事务。
- 什么是 fencing token,解决什么问题? 答:故障切换时由协调方颁发的单调递增纪元号,存储层拒绝携带旧纪元号的写入,防止旧主「复活」后造成脑裂写冲突。
公式或模型
一致性窗口 ≈ 复制延迟 lag;写后读不一致概率 ≈ lag / 读间隔(间隔小于 lag 的读都可能踩空)。可用性权衡:同步复制可用性 = 全体副本可用性之积(任一故障即不可写)。
图示
直观类比
异步复制像群发消息后不等回音就继续开会:快,但有人根本没收到;半同步像点名确认「至少一个人收到」;完全同步像全员签到才继续——最稳也最容易被一个人卡住全场。
与其他知识点的关系
kp-020 的日志流是复制的原料;kp-026 用共识协议把「手动切换 + fencing」升级为自动化安全选主;kp-025 给复制模式与一致性、可用性的理论边界。
延伸阅读
- 《数据密集型应用系统设计》(Martin Kleppmann)第 5 章
- 《数据库系统概念》(Abraham Silberschatz 等)分布式数据库章节