Skip to content

第五章:复制

1. 复制的目标与代价

复制用于提升可用性、容错能力与读扩展能力,但会引入复制延迟、冲突处理和一致性语义选择。

2. 单主复制(Leader-Follower)

2.1 基本机制

所有写请求进入 LeaderFollower 订阅并按顺序重放变更日志。客户端通常“写主读从”或关键读走主库。

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 QuorumHinted Handoff 提高可用性,但会削弱一致性保证。
  • 反熵修复存在滞后窗口。
  • 并发写入仍需冲突检测与合并策略。

5.4 并发写检测

通过 happens-before 关系判断“覆盖”与“并发”:

  • 覆盖关系:新版本可安全替代旧版本。
  • 并发关系:保留兄弟版本,交由业务合并。

版本向量是常见实现手段。

6. 选型建议

  • 强一致写路径优先单主 + 明确故障切换策略。
  • 跨地域多活优先多主,但必须先定义冲突语义。
  • 超大规模高可用写路径可选无主,但要接受最终一致与冲突合并复杂度。