第五章:复制
1. 复制的目标与代价
复制用于提升可用性、容错能力与读扩展能力,但会引入复制延迟、冲突处理和一致性语义选择。
2. 单主复制(Leader-Follower)
2.1 基本机制
所有写请求进入 Leader,Follower 订阅并按顺序重放变更日志。客户端通常“写主读从”或关键读走主库。
2.2 同步、异步与半同步
- 同步复制:一致性强,但写延迟高、可用性受慢副本影响。
- 异步复制:吞吐高,但主故障时可能丢失最近已确认写入。
- 半同步:折中方案,常要求至少一个副本确认。
2.3 故障切换要点
- 失效检测:心跳 + 超时。
- 选主:优先数据最新副本。
- 重配置:客户端与从库切换到新主。
需重点防范脑裂,生产环境通常配合仲裁与 fencing 机制。
2.4 复制日志实现
- 语句复制:简单但易受非确定语句影响。
- 物理日志复制(如
WAL):高效但与存储实现耦合。 - 逻辑复制(行变更):解耦性更好,适合
CDC。
3. 复制延迟与读一致性
异步复制下常见“读到旧数据”,可通过会话一致性策略改善体验。
3.1 Read-Your-Writes
用户写后读应看到自己的更新。常见做法是“用户关键读强制走主”或“按写入时间戳约束从库选择”。
3.2 Monotonic Reads
同一用户多次读取不应倒退到更旧版本,可通过会话粘性路由到固定副本。
3.3 Consistent Prefix Reads
有因果关系的数据应按前缀顺序可见,避免“先看到结果,后看到原因”。
4. 多主复制(Multi-Leader)
4.1 适用场景
- 多机房本地写入。
- 离线客户端回连同步。
- 协同编辑等多点写入业务。
4.2 冲突处理策略
- 避免冲突:按用户或分区定向写入。
- 自动收敛:
LWW、版本向量、业务合并函数。 - 人工介入:保留冲突版本供最终裁决。
LWW 简单但会丢数据,强业务语义场景应优先保留冲突并显式合并。
4.3 拓扑影响
全互联拓扑容错好但易乱序,链式拓扑简单但故障传播明显。拓扑设计需与冲突语义和链路质量一起评估。
5. 无主复制(Leaderless)
5.1 核心机制
客户端并行读写多个副本,通过版本比较与读修复实现最终收敛。
5.2 Quorum 模型
在副本数 N 下,若写确认数 W 与读确认数 R 满足 W + R > N,理论上可读到最新值。
5.3 局限与边界
Sloppy Quorum与Hinted Handoff提高可用性,但会削弱一致性保证。- 反熵修复存在滞后窗口。
- 并发写入仍需冲突检测与合并策略。
5.4 并发写检测
通过 happens-before 关系判断“覆盖”与“并发”:
- 覆盖关系:新版本可安全替代旧版本。
- 并发关系:保留兄弟版本,交由业务合并。
版本向量是常见实现手段。
6. 选型建议
- 强一致写路径优先单主 + 明确故障切换策略。
- 跨地域多活优先多主,但必须先定义冲突语义。
- 超大规模高可用写路径可选无主,但要接受最终一致与冲突合并复杂度。