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 消息。这减少了 网络往返、提升了吞吐,且不引入人为的批处理延迟——这是一项对延迟毫无代价的吞吐收益。
follower 到底是怎么重新加入的
Section titled “follower 到底是怎么重新加入的”leader 宣布 term 之后,回归的 follower 会依次走过最多三个具名状态(对应 OSS 源码里的 ElectionState):
| 状态 | 做什么 |
|---|---|
FOLLOWER_LOG_REPLICATION | 把缺失的已完成 term 从源 archive 复制进自己的本地 archive。 |
FOLLOWER_REPLAY | 把本地 log 通过 consensus module 和你的 service 回放一遍。 |
FOLLOWER_CATCHUP | 接收 leader 针对当前 term 的 archive 回放,并汇入实时流。 |
具体会走到哪几个阶段,取决于这个节点落后多少——几乎跟得上的节点可能直接进追赶,滞后的节点则要三个阶段都走完,才能到 FOLLOWER_READY。
五项安全保证
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(状态机安全性) | 所有节点以相同顺序应用相同的操作 |
本站与 Adaptive Financial Consulting Limited 或 Aeron 项目无任何关联,未获其背书或赞助。 Aeron 是 Adaptive Financial Consulting Limited 的注册商标。
Aeron 是 Adaptive Financial Consulting Limited 在英国及其他国家/地区的商标。