跳到内容

4.2 Leaderless 复制、Quorum 与副本修复

Leaderless 系统允许协调器把读写发送给一组副本,不依赖每个分片的固定 Leader。它可以在部分副本不可用时继续服务,但需要显式处理并发版本、过期副本和长期修复。

N、W、R 只描述确认集合

  • N:一个分区的副本数;
  • W:写成功需要的副本确认数;
  • R:读返回需要的副本响应数。

W + R > N 使读写集合至少相交,W > N/2 使两个成功写集合相交。相交能提高读到已确认版本的机会,但不是完整的线性一致性证明。

系统仍要解决:并发协调器、时钟冲突、失败写残留、读修复、删除和客户端重试。需要 compare-and-set 语义时,应使用产品明确提供的 LWT/共识路径。

Cassandra 写路径

协调器根据 partition key 找到副本,并等待请求 consistency level 所需的确认。副本通常先追加 commit log,再更新内存结构,之后刷成不可变 SSTable。

text
client
  → coordinator
      ├→ replica A: commit log + memtable
      ├→ replica B: commit log + memtable
      └→ replica C: commit log + memtable

Memtable 刷盘后形成多个 SSTable,后台 compaction 合并它们。追加写提高吞吐,却把读放大、空间放大和 compaction 尾延迟带入运营成本。

读路径需要合并版本

协调器从满足 consistency level 的副本取得数据或摘要,比较版本并返回胜出结果。过期副本可以通过 read repair、hinted handoff 和 anti-entropy repair 逐步追赶。

这些机制承担不同职责:

  • hinted handoff 暂存对短时不可用副本的写提示;
  • read repair 在读取时发现并修复差异;
  • repair 系统性比较副本范围,修复长期分歧。

没有定期 repair,最终一致性只是愿望。修复间隔还必须小于 tombstone 和删除回收相关窗口,否则已删除数据可能从长期离线副本“复活”。

Last-write-wins 依赖时间戳语义

若冲突按时间戳选择最新值,时钟漂移或错误客户端时间可能让旧业务写覆盖新写。LWW 能确定收敛结果,不代表结果符合业务因果。

可以通过单一写入所有者、服务端时间戳、版本号、条件更新或 CRDT 等方式减少冲突。选择前要区分:

  • 同一字段的并发更新是否可以任意胜出;
  • 删除和更新并发时谁赢;
  • 合并是否满足交换、结合和幂等;
  • 业务是否需要向用户暴露冲突。

分区设计决定性能上限

Cassandra 表围绕查询设计。Partition key 决定路由和数据共置,clustering columns 决定分区内排序。

过小分区增加元数据和跨分区扇出,过大分区造成热点、长 GC/compaction 和恢复困难。避免用 ALLOW FILTERING 掩盖未建模查询,也不要把跨分区 batch 当成一般事务。

删除比写入更复杂

分布式副本不能立即物理删除,否则离线副本恢复后会把旧值再次传播。删除先写 tombstone,再在满足修复和保留条件后回收。

大量 tombstone 会增加读扫描和 compaction 压力。TTL、时间序列表和高频删除必须在 schema 阶段考虑,而不是上线后只调一个阈值。

监控信号

  • 每个 consistency level 的延迟和不可用错误;
  • 分区大小、热点 key 和 coordinator 扇出;
  • pending compaction、SSTable 数和磁盘放大;
  • repair 进度、最久未修复范围和 streaming 流量;
  • tombstone 扫描、丢弃和 GC 窗口;
  • dropped mutations、hint backlog 和副本版本差异。

下一课对比大文件系统和全球事务数据库,理解同为“分布式存储”为什么采用完全不同的协调成本。

参考资料

Built with VitePress | Software Systems Atlas