Cloudflare Meerkat: 通过 QuePaxa 实现全球分布式共识

Cloudflare Meerkat: 通过 QuePaxa 实现全球分布式共识

Cloudflare Meerkat 通过消除基于 Leader 的协议中存在的“超时暴政”,提供高可用性的全球共识。

Cloudflare 推出了 Meerkat,这是一个实验性的分布式共识服务,旨在管理分布在 330 多个全球数据中心的关键控制平面状态。与依赖单一权威 Leader 的传统共识系统不同,Meerkat 利用了 QuePaxa 算法,允许任何副本(replica)驱动共识。这种架构确保了即使当前 Leader 故障或网络延迟剧烈波动,系统仍能保持读写可用性,从而防止了 Cloudflare 此前在使用基于 Raft 的系统时遇到的服务中断问题。

全球控制平面数据的要求

控制平面数据——例如资源放置信息或数据库 Leader 状态——需要结合强一致性和高容错性,才能在广域网(WAN)上可靠运行。

线性一致性 (Linearizability)

Meerkat 旨在实现 线性一致性,这是最强的一致性模型。在一个线性一致的系统中,所有操作都按照它们在现实时间中发生的顺序进行排序。这确保了在执行写操作后进行的任何读操作都保证能看到该写操作,无论客户端联系的是哪个全球副本。

容错性与正确性

Meerkat 旨在在以下条件下保持正确性和可用性:

  • 多数派可用性: 只要大多数机器(在 2f+1 个系统的中,为 f+1 个)存活并进行通信,系统就能保持读写可用。
  • 客户端访问: 客户端可以与任何连接到大多数存活机器的机器进行交互。
  • 非拜占庭故障: 只要没有参与者是恶意攻击的,系统就能保持正确,尽管它能够处理机器崩溃、重启和网络退化。

架构:Meerkat 日志与 QuePaxa

Meerkat 作为基础架构,应用程序(如事务型键值 (KV) 存储或租赁系统)可以构建在其之上。

分布式日志

Meerkat 的核心是维护一系列“槽位”(slots)。每个槽位要么是空的,要么包含一个已决定的事件。

  • 通过槽位实现一致性: 如果两个副本对特定槽位的某个值达成一致,那么这些值必须是相同的。
  • 线性化读取: 为了确保线性一致性,即使是 get 请求也会创建日志事件。如果一个副本尝试从它认为为空的槽位读取,但大多数副本已经为该槽位决定了一个值,那么该副本将被迫在完成读取之前与大多数副本进行同步,从而有效地在之前的写操作之后将读取线性化。

为什么选择 QuePaxa 而非 Raft?

Cloudflare 从 Raft 转向 QuePaxa 是为了解决广域网中固有的特定可用性问题:

  1. 消除 Leader 瓶颈: 在 Raft 中,所有写操作必须通过单一 Leader。如果 Leader 故障或变慢,整个系统都会阻塞。在 QuePaxa 中,任何副本都可以驱动最新槽位的共识。
  2. 避免超时问题: Raft 依赖超时来触发新的 Leader 选举。在不可预测的 WAN 中,超时设置过短会导致频繁且不必要的选举,而超时设置过长则会增加停机时间。QuePaxa 不会因为超时而停止进展。
  3. 建设性干预: 虽然 Raft 的 Leader 竞选可能会相互干扰并阻塞写操作,但 QuePaxa 允许多个副本同时提议值;这些提议会协同工作以决定一个值,而不是产生破坏性的干扰。

性能权衡与优化

由于共识需要多次网络往返,Meerkat 并不打算作为通用数据库使用,而是用于写入频率较低的控制平面数据。

延迟约束

决策延迟与大多数副本之间的网络延迟成正比。如果由 Leader 驱动,提议通常需要一次往返;如果由非 Leader 驱动,则需要三次或更多次往返。

性能缓解措施

为了提高吞吐量并降低感知延迟,Meerkat 采用了几种策略:

  • 批量处理 (Batching): 副本可以将会多个写操作组合成单个提议。
  • 副本放置 (Replica Placement): 对于不需要完全全球分布的服务,开发者可以将副本放置得更近一些,以减少往返时间。
  • 陈旧读取 (Stale Reads): 对于不需要严格线性一致性的应用,可以从副本的本地数据进行读取,而不触发共识轮次。
  • 捆绑操作 (Bundled Operations): KV 存储支持在单个共识轮次内进行通用事务和比较并交换 (CAS) 写操作。

当前状态

Meerkat 目前是一个内部实验性服务。拥有多达 50 个全球副本的概念验证部署已经证明,即使在 Leader 频繁故障的情况下,集群仍能持续运行,且错误率不会增加。

Sources