1. 核心概念
RabbitMQ 的高可用主要体现在集群模式的选择上。原生的 RabbitMQ 集群分为两种模式:
- 普通集群模式(Standard Cluster):仅同步元数据(Metadata),不同步消息内容。
- 镜像队列模式(Mirror Queue):既同步元数据,也同步消息内容(这是实现 HA 的传统方式)。
- 仲裁队列(Quorum Queues):RabbitMQ 3.8+ 引入的新一代高可用模型,基于 Raft 协议。
2. 原理与架构
2.1 普通集群模式(非高可用)
- 原理:多台机器组成集群,Queue 的元数据(定义)在所有节点同步,但 Queue 的实际消息数据只存储在创建它的那个节点(Master)上。
- 缺点:如果 Master 节点宕机,该队列的消息将无法访问,直到节点恢复。如果磁盘损坏,消息丢失。此模式仅用于扩展吞吐量,不具备高可用性。
2.2 镜像队列模式(Classic HA)
- 原理:将队列的消息数据在集群的其他节点上进行全量复制。
- Master:处理所有读写请求。
- Slave:从 Master 同步数据。如果 Master 宕机,集群会自动将某个 Slave 提升为 Master。
- 配置:通过 Policy 设置
ha-mode: all(所有节点镜像)或ha-mode: exactly(指定副本数)。 - 缺点:
- 性能损耗大:所有消息都要同步到所有 Slave,网络带宽压力大。
- 同步阻塞:新节点加入时,全量同步历史数据会导致集群性能瞬间下降。
2.3 仲裁队列(Quorum Queues - 推荐)
- 原理:基于 Raft 一致性协议 实现。
- 特点:
- 数据安全性更高:只要半数以上节点写入成功即视为成功,避免了镜像队列的“脑裂”风险。
- 性能更稳:相比镜像队列,在网络分区或节点故障时表现更稳定。
- 限制:不支持非持久化消息(消息必须落盘)。
3. 性能与分区考量
- 网络分区(Network Partition):RabbitMQ 对网络分区非常敏感。需配置
cluster_partition_handling策略:pause_minority:暂停少数派节点(推荐)。autoheal:自动恢复,可能会丢数据。
- 客户端连接:客户端应连接到 Load Balancer(如 HAProxy),由 LB 将请求分发到集群节点,实现客户端的高可用。
4. 示例与总结
回答总结: “RabbitMQ 的高可用不能靠‘普通集群模式’,因为它只同步元数据。 传统做法是开启镜像队列(Mirror Queue),配置策略让消息在多个节点间全量同步,Master 挂了 Slave 顶上。但镜像队列性能开销大,且在网络分区时容易出问题。 现在更推荐使用 RabbitMQ 3.8 引入的仲裁队列(Quorum Queues),它基于 Raft 协议,在保证数据一致性的同时,性能和稳定性都优于镜像队列。 此外,在架构上还需要配合 HAProxy + Keepalived 做前端的负载均衡和 VIP 漂移,保证客户端连接的高可用。”
# 开启镜像队列策略示例(命令行)
# 匹配所有以 'ha.' 开头的队列,在所有节点上进行镜像
rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}'