Quorum 与 Raft
Quorum Queue 基于 Raft 共识协议实现高可用。理解 Raft 是理解 Quorum Queue 行为的关键。
1. Raft 协议核心
Raft 是一种分布式共识算法,保证多个节点对日志顺序达成一致。
Leader ──日志复制──▶ Follower 1
──▶ Follower 2
写入需要多数派确认(多数派包含 Leader 自身):
3 成员:至少 2 个成员确认
5 成员:至少 3 个成员确认多数派复制与日志提交不是一回事。Raft 的提交有专门规则,入门阶段只需记住,RabbitMQ 的 Publisher Confirm 面向发布者,Raft 的日志提交是底层状态复制,两者分属不同层次。
2. Quorum Queue 中的 Raft
Producer ──▶ Leader Node ──Raft 日志──▶ Follower 1
──▶ Follower 2
Consumer ◀── Leader Node(消费由 Leader 协调)- 发布:消息被队列多数副本接受后,RabbitMQ 才向发布者返回 Publisher Confirm。Confirm 只表示消息达到队列的数据安全条件,不表示消费者已经处理成功。未收到 Confirm 不代表消息一定没写入,发布端重试时需要考虑重复消息。
- 消费:消费操作由 Leader 协调处理,Quorum Queue 不支持从 Follower 读队列消息。消费者连接的 RabbitMQ 节点不一定是队列 Leader 所在节点。
- Leader 选举:Leader 崩溃后,剩余成员发起选举。选举完成前,依赖 Leader 的发布和消费操作可能阻塞、超时或失败。
3. Leader 选举
Leader 崩溃
→ Follower 发现心跳超时
→ Follower 转为 Candidate,发起投票
→ 多数节点投票 → 新 Leader 当选选举耗时取决于故障检测、网络延迟、节点负载和是否反复选举失败,协议不保证在固定时间内完成。生产环境应通过故障注入测试观察实际恢复时间,而不是把某个固定秒数当作可用性承诺。
4. 日志复制与持久性
Producer ──发布──▶ Leader ──复制日志──▶ Follower 1
──▶ Follower 2
│
▼
多数副本接受消息
│
▼
Publisher Confirm持久性边界
已收到 Publisher Confirm 的消息,在多数副本没有永久丢失、存储与协议符合安全假设的前提下,Quorum Queue 提供相应的数据安全保证。尚未收到 Confirm 的消息可能已经写入,也可能仍在传输或处理中,发布端不能把「未收到 Confirm」理解为「消息肯定没写入」。
5. Quorum Queue 的脑裂处理
Raft 通过多数派选举和日志安全规则防止脑裂:
- 网络分区时,少数派分区的节点无法获得多数投票,不能选出 Leader,也无法独立提供正常的队列服务
- 多数派分区具备选举 Leader 和继续处理队列操作的条件
- 网络恢复后,落后副本从当前 Leader 获取缺失日志,逐步同步到与多数派一致的状态
6. 性能特征
Quorum Queue 用持久化和多数派复制换取数据安全与高可用,性能评估不能只看单条消息的写入延迟,还要看持续吞吐量、消费速度和故障恢复时间。
发布确认需要等多数副本接受消息,网络往返时间和磁盘写入性能会直接影响确认延迟。消费吞吐量受消费者预取、确认频率、消息大小和队列积压影响。增加队列成员会增加复制开销,可能降低吞吐量,实际影响应通过压测确认。Leader 选举和副本恢复期间,服务会短暂不可用。
性能数据必须在目标环境压测,并记录 RabbitMQ 版本、节点配置、磁盘类型、网络条件、消息大小、发布确认方式和消费者预取等条件。
7. 集群大小建议
| 队列成员数 | 可容忍成员故障数 | 适用场景 |
|---|---|---|
| 3 | 1 | 常见的高可用配置 |
| 5 | 2 | 需要容忍更多成员故障 |
| 7 | 3 | 有明确需求且经过性能验证 |
通常优先选择 3 个成员,需要容忍 2 个成员故障时再考虑 5 个成员。一般不推荐偶数成员数。3 个和 4 个成员都只能容忍 1 个成员不可用,但 4 个成员需要 3 个成员才能形成多数派,增加了复制成本,却没有增加可容忍的成员故障数。