Aeron Cluster 与 Raft 共识
Aeron Cluster 是面向有状态、事件驱动应用的容错集群。它以微秒级延迟提供内存中状态,底层有一份 Raft 复制的日志作为支撑,确保你永远不会丢失任何已提交的事件。本页介绍其设计原则、让 Raft 得以运转的 两个 RPC、Aeron 在其之上叠加的改进,以及让整套机制对撮合引擎而言足够安全的五项安全保证。
至于字节级的内部细节——日志布局、term 文件、archive 录制——请参阅 The Aeron Files。本页是运维者的心智模型,而非线路(wire)格式。
Aeron Cluster 构建在 Aeron Transport 之上,而非 TCP。这一选择决定了其余的整体设计。
- 极高吞吐与极低延迟 —— 构建在 Aeron Transport 之上,而非 TCP。
- 状态完全保存在内存中 —— 热路径上没有数据库。
- 输入事件写入持久化存储 —— 通过 Aeron Archive 实现,用于节点恢复。
- 复制到其他节点与站点 —— 基于 Raft 的共识以保证一致性。
- 单一集群上承载多个服务 —— 在多个服务间共享共识基础设施。
各层的堆叠方式如下:
所有状态都驻留在内存中。持久化日志(Archive)只为恢复而存在。这正是实现微秒级处理的关键:热路径上 没有磁盘 I/O,没有数据库查询,也没有对外部系统的网络调用。结果会直接体现在你的延迟剖面上——p50 和 p99 保持很低,因为请求无需触及磁盘或远程服务即可产生响应。
两个 Raft RPC
Section titled “两个 Raft RPC”Raft 共识只用到两个 RPC。这就是整个协议的全部接口面。
RequestVote RPC
Section titled “RequestVote RPC”- 由候选者(candidate)发起,在 leader 选举期间收集选票。
- 节点转入候选者状态,递增其 term,给自己投票,并向所有其他节点发送 RequestVote。
- 其他节点在候选者的日志至少与自身一样新(up-to-date)时,才会投出选票。
AppendEntries RPC
Section titled “AppendEntries RPC”- 由 leader 发起,用于两个目的:
- 日志复制 —— 向 follower 发送新的日志条目。
- 心跳(Heartbeat) —— 空的 AppendEntries,用于维持领导权(防止 follower 发起选举)。
为什么只有两个?这种简洁是刻意为之的。消息类型越少,就意味着边界情况越少、bug 越少,形式化验证也越 容易。Raft 中的一切要么是”谁应当成为 leader?“(RequestVote),要么是”leader 这样说” (AppendEntries)。
Aeron 的共识实现
Section titled “Aeron 的共识实现”Aeron Cluster 用三个基本构件来实现 Raft,并在原始论文之上做了若干改进。
构建在以下之上:
- Aeron Transport —— 用于节点间通信(UDP,而非 TCP)。
- Aeron Archive —— 用于持久化日志存储。
- Consensus Module —— Aeron 的 Raft 实现。
相较于 Raft 论文的改进
Section titled “相较于 Raft 论文的改进”1. 选举前的 canvass 阶段。 在节点成为候选者并发起正式选举之前,它会先向其他节点进行试探 (canvass),以检查选举是否会成功。这避免了会扰乱集群的无谓选举——一个节点不会发起一场它明知会输掉 的选举。
2. 节点间的并行复制。 leader 同时向所有 follower 发送 AppendEntries,而非逐个串行发送。因此,提交 延迟受限于法定多数(quorum)中最慢的那个节点,而不是所有节点之和。
3. 复制过程中的自然批处理。 当多个日志条目可用时,会被批量打包进单个 AppendEntries 消息。这减少了 网络往返、提升了吞吐,且不引入人为的批处理延迟——这是一项对延迟毫无代价的吞吐收益。
五项安全保证
Section titled “五项安全保证”Raft 的正确性建立在五项保证之上。它们共同确保集群永远不会出现分歧(diverge)。
1. 选举安全性(Election Safety)
Section titled “1. 选举安全性(Election Safety)”在任一给定 term 内,最多只能选出一个 leader。
这可以防止脑裂(split-brain)——你绝不会出现两个节点都认为自己是同一 term 编号下的 leader 的情况。它 通过要求获得多数票来强制保证。
2. Leader 仅追加(Leader Append-Only)
Section titled “2. Leader 仅追加(Leader Append-Only)”leader 绝不覆盖或删除其日志中已有的条目。
leader 只追加新条目;它从不修改历史。这使得 leader 的日志成为一个单调增长、不可变的序列——这对一致性 至关重要。
3. 日志条目一致性(日志匹配,Log Matching)
Section titled “3. 日志条目一致性(日志匹配,Log Matching)”如果两份日志中存在一个具有相同 index 和 term 的条目,那么这两份日志在该 index 之前的所有条目都完全 相同。
这是让 Raft 得以运转的归纳性质:如果两个节点在条目 (index=42, term=5) 上达成一致,那么它们在条目 1–41 上也必然一致。它通过 leader 在每个 AppendEntries 中都包含前一条目的 index 和 term 来强制保证 ——follower 会拒绝不匹配的条目。
4. Leader 完整性(Leader Completeness)
Section titled “4. Leader 完整性(Leader Completeness)”如果某个日志条目在某一 term 内被提交,那么该条目将存在于所有更高编号 term 的 leader 的日志中。
一旦某个条目被提交(已复制到多数节点),它就永远不会丢失——每一个未来的 leader 都必然拥有它。它通过 投票规则来强制保证:节点不会把票投给日志完整度低于自身的候选者。
5. 状态机安全性(State Machine Safety)
Section titled “5. 状态机安全性(State Machine Safety)”如果某台服务器已将某一 index 处的日志条目应用到其状态机,那么其他任何服务器都绝不会在同一 index 处 应用一个不同的日志条目。
这是终极的一致性保证:所有节点都将相同的操作序列应用到各自的状态机上。结合确定性执行,每个节点都会 收敛到完全相同的状态。
它们如何彼此契合
Section titled “它们如何彼此契合”| 保证 | 它确保了什么 |
|---|---|
| Election Safety(选举安全性) | 每个 term 只有一个 leader |
| Leader Append-Only(Leader 仅追加) | leader 从不重写历史 |
| Log Matching(日志匹配) | 对单个条目的一致即对所有先前条目的一致 |
| Leader Completeness(Leader 完整性) | 已提交的条目在 leader 更替后依然存在 |
| State Machine Safety(状态机安全性) | 所有节点以相同顺序应用相同的操作 |