RabbitMQ 高可用与仲裁队列
集群解决节点数量问题,高可用解决"节点挂了消息还在"的问题:让队列在多个节点上持有副本,主节点故障时自动切换到其它副本继续服务。历史上靠镜像队列实现,现在官方推荐仲裁队列。
镜像队列:历史方案
镜像队列(Mirrored Queue)是 3.x 时代的经典高可用方案,通过策略把匹配的队列镜像到集群若干节点,主节点故障时从镜像中提升新主:
# 对名称匹配 q. 开头的所有队列做全节点镜像
rabbitmqctl set_policy ha-all "^q\." \
'{"ha-mode":"all","ha-sync-mode":"automatic"}'
ha-mode 可选 all(全部节点)、exactly(指定个数)、nodes(指定节点);ha-sync-mode 控制镜像同步时机。
镜像队列的局限明显:全节点镜像让每台机器都存全量消息,扩展性差;主从同步与脑裂恢复逻辑复杂,出现过网络分区后消息不一致的情况;镜像同步过程还会拖慢新加入的节点。
官方从 3.8 起就推荐由仲裁队列接棒镜像队列,较新版本(4.x 起)更以仲裁队列与流队列作为复制队列的主要形态。新项目不建议再新建镜像策略,存量集群逐步迁移。
仲裁队列 quorum:推荐方案
仲裁队列基于 Raft 共识算法:消息写入要在"多数派"节点上确认才算成功,节点间无固定主从之分,靠投票选主,天然避免脑裂。副本数建议用 3 或 5 的奇数:3 副本可容忍 1 台故障,5 副本可容忍 2 台故障。
# 声明仲裁队列:x-queue-type=quorum 是关键
rabbitmqadmin declare queue name=q.quorum durable=true \
arguments='{"x-queue-type":"quorum"}'
# 需要固定副本数可在声明时附加 x-quorum-initial-group-size 参数
仲裁队列专为"持久化 + 可靠 + 复制"设计,消息一律按持久化处理,配合多数派确认能扛住节点宕机;代价是写路径开销大于单副本经典队列,且不支持 exclusive 队列等少数经典特性,选型时按业务评估。
消费者连集群任意节点都能消费仲裁队列,主副本切换对客户端基本透明,但切换瞬间连接会被断开,客户端需要重连(见下文)。
镜像队列与仲裁队列对比
| 维度 | 镜像队列(历史) | 仲裁队列 quorum |
|---|---|---|
| 复制方式 | 主从异步镜像 | Raft 多数派共识 |
| 脑裂风险 | 有 | 天然避免 |
| 可靠性 | 同步窗口内可能丢 | 持久化 + 多数派确认 |
| 适用 | 旧系统存量 | 新系统持久化高可用 |
流队列 streams(一句话)
RabbitMQ 还提供流队列 streams:日志式追加存储、面向高吞吐事件流,消息可被多个消费者按 offset 重复读取,不随消费删除。它的定位是日志、审计、事件重放,不是替代普通队列的业务消息通道。
故障转移时的行为提醒
- 单副本经典队列:所在节点宕机,队列整体不可用,节点恢复后才恢复;
- 镜像/仲裁队列:主副本故障自动切到其它副本,期间连接被断开,客户端需要实现"重连 + 重新声明"逻辑;
- 无论哪种队列,断开时未确认的消息都会重新投递,消费端要保持幂等,接受 at-least-once 语义。
小结
镜像队列是历史方案(ha-mode=all 等策略),局限明显,已被仲裁队列接棒;仲裁队列用 Raft 多数派复制,3 副本可容忍 1 台故障,是较新版本持久化高可用队列的推荐选择,客户端再配合重连与幂等即可。