1. 为什么非要用这三件套,单节点和普通集群差在哪
接手某内部订单系统的消息平台时,老板给我的要求只有一句话:“RabbitMQ 不能挂,挂了全公司消息就断了。”当时线上只跑了一个单节点 RabbitMQ,队列一堆积,消费者一抖动,整个链路就跟着卡。后来我把 HAProxy、Keepalived(VIP) 和 RabbitMQ 的组合搭起来,做成高可用镜像队列,才算是把这块彻底扛住了。
先说结论:这套方案的核心不是“多装几个 rabbitmq-server 进程”,而是让三层各自负责一个高可用角色——HAProxy 负责把客户端流量分发到多个节点,Keepalived 负责给 HAProxy 提供一个不会因为机器故障而失效的虚拟 IP,RabbitMQ 镜像队列则负责把队列数据在每个节点上都保存一份副本。三层缺一不可。
1.1 单节点和普通集群的硬伤
单节点 RabbitMQ 的问题不用多说:进程崩溃、磁盘写满、内存 OOM、机器宕机,任何一个问题都会让队列不可用,消息发不进来也消费不掉。消息要么等着节点恢复,要么因为持久化配置不当而直接丢失。
很多人以为“多装几个节点组成集群”就算高可用了,这是最大的误区。RabbitMQ 的普通集群模式,队列数据并不是在所有节点上各存一份。它只是把集群里的队列分布在不同节点上,消息路由到一个节点后,数据就只存在那个节点。如果那个节点挂了,它上面承载的队列在节点恢复前是不可用的。消费者哪怕连到集群里的另一个节点,也读不到这个队列的历史消息。
举个直观例子:两个节点组成普通集群,队列 Q 被分配到节点 A 上,那么消息都写在 A。节点 B 上虽然也能看到队列 Q 这个“逻辑实体”,但它没有副本数据。A 一关机,Q 就没了入口,直到 A 恢复为止。这和一个节点有什么区别?区别只是“别的队列可能存活”,但你的队列是否存活完全看运气。
1.2 三件套各自解决什么问题
- HAProxy:解决“客户端到底连谁”的问题。客户端只认一个地址,HAProxy 把连接分担到多个 RabbitMQ 节点,某个节点不可用时自动摘除。
- Keepalived(VIP):解决“HAProxy 本身挂了怎么办”的问题。两台 HAProxy 之间通过 VRRP 协议抢同一个虚拟 IP,正常情况下 IP 在主节点上,主节点故障后 IP 漂移到备节点,客户端连接地址不变。
- 镜像队列:解决“数据副本”的问题。队列开启镜像策略后,一个队列在主节点上写入,副本会被同步到其他节点。任何节点宕机都不影响已同步数据的可用性。
这里我把“镜像队列”单独拎出来强调,是因为标题里最容易被人忽略的就是这四个字。前面两个组件解决的是“连接不中断”,但连接不中断不等于数据不丢。如果没有镜像队列,你把流量负载均衡到两台 RabbitMQ 上,其中一台宕机时,它上面队列的消息就是不可用的,这不是真正的高可用。
1.3 合设部署形态,是我最推荐的小规模方案
这套组合有两种常见部署方式:一种是 RabbitMQ 一台机器、HAProxy/Keepalived 单独两台机器;另一种是 RabbitMQ、HAProxy、Keepalived 全部落在同样的两个节点上,俗称“合设”。
对于大多数中小规模业务,两个节点的合设方案更省机器,也更容易维护。每个节点上都跑 RabbitMQ、HAProxy、Keepalived,两台互为冗余。客户端访问虚拟 IP,虚拟 IP 落在哪台,流量就先进哪台 HAProxy,再由 HAProxy 把 AMQP 流量分发给本机和另一台 RabbitMQ。节点 A 整机宕机后,VIP 漂移到节点 B,节点 B 上的 HAProxy 继续给客户端提供入口,同时把流量分发给自己或者其他健康节点。
我个人在生产上跑过这个形态,消息量不大时性能完全够用。如果单节点吞吐量接近瓶颈,就不要合设,应该把负载均衡层独立出去,用更专业的入口设备承接。
2. 节点规划与基础环境:先想清楚再动手
2.1 我采用的节点与网络规划
以两台机器为例,规划如下:
| 主机名 | IP 地址 | 角色 | 说明 |
|---|---|---|---|
| amq-node-1 | 192.168.56.11 | RabbitMQ + HAProxy + Keepalived | 主节点,VRRP 优先级高 |
| amq-node-2 | 192.168.56.12 | RabbitMQ + HAProxy + Keepalived | 备节点,VRRP 优先级低 |
| VIP | 192.168.56.100 | 客户端统一入口 | 实际由 Keepalived 动态绑定到某一台 |
为什么主机名这么重要?因为 RabbitMQ 集群依赖 Erlang 集群通信,Erlang 节点名字用的是短主机名,比如rabbit@amq-node-1。如果/etc/hostname没有固定,或者/etc/hosts里没有正确解析对方主机名,集群 join 的时候就会报一堆 “unable to connect” 或者 “hostname mismatch” 的错。
2.2 容易被忽略的系统层配置
接下来不是直接装包,而是先把操作系统层面的雷排掉:
固定 hostname,并写入双方 hosts。我在
/etc/hosts里固定写死:192.168.56.11 amq-node-1 192.168.56.12 amq-node-2千万不要依赖 DHCP 分配的域名。
开启时间同步。RabbitMQ 节点间的心跳、消息确认、日志时间戳都依赖相对一致的时间。用 chrony 或者 systemd-timesyncd 随便一个都可以,但必须同步。
调整内存和 Swap 参数。RabbitMQ 对内存水位非常敏感,默认阈值是 40%,超过阈值会阻塞生产者。建议把
vm.swappiness调低,避免系统频繁把进程内存换到 swap 导致延迟飙升。防火墙端口放通。节点间需要互相访问 Erlang 端口,客户端需要访问 VIP 上的 AMQP 端口。端口规划:
| 端口 | 用途 | 放通范围 |
|---|---|---|
| 4369 | epmd 端口,Erlang 节点发现 | 集群节点之间 |
| 25672 | RabbitMQ 集群内部通信 | 集群节点之间 |
| 5672 | AMQP 客户端入口 | 客户端 → HAProxy/VIP |
| 15672 | RabbitMQ 管理界面 | 管理网段 → HAProxy/VIP |
注意:HAProxy 监听在0.0.0.0上,VIP 只是绑定在网卡上的一个辅助地址,所以防火墙只要放行 VIP 对应的入口,客户端就能正常通过。
2.3 安装组件与启用管理插件
我用的是支持 RabbitMQ 3.8 以上版本的 Linux 发行版,安装命令大致是:
sudo dnf install -y rabbitmq-server haproxy keepalived安装完成后,先把服务设为开机自启:
sudo systemctl enable --now rabbitmq-server haproxy keepalivedRabbitMQ 管理插件按需启用,一般建议打开:
sudo rabbitmq-plugins enable rabbitmq_management sudo systemctl restart rabbitmq-server管理界面默认只能从本机访问 guest 账号,生产环境一定要新建专用账号,并赋予对应权限,后面测试用。
3. RabbitMQ 集群初始化与镜像队列策略的正确姿势
3.1 统一 Erlang Cookie,一个细节挡掉一半初级错误
RabbitMQ 节点之间通过 Erlang 分布式节点通信,而 Erlang 节点通信依靠一个共享 cookie 做认证。cookie 文件在/var/lib/rabbitmq/.erlang.cookie。
搭建集群的第一件事,是把第一个节点上的 cookie 复制到第二个节点,并确保权限正确:
sudo cp /var/lib/rabbitmq/.erlang.cookie /var/lib/rabbitmq/.erlang.cookie sudo chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie sudo chmod 600 /var/lib/rabbitmq/.erlang.cookie sudo systemctl restart rabbitmq-server这里有个容易踩的坑:复制的时候注意文件内容末尾不要多出换行,也不要有多余空格。cookie 一个字节不对,后面 join cluster 必失败。我见过有人排查了一个小时,最后发现是复制命令多打了一个空格导致 cookie 不一致。
3.2 集群加入的顺序和方法
先在 amq-node-1 上确认 RabbitMQ 已经启动,然后在 amq-node-2 上执行:
sudo rabbitmqctl stop_app sudo rabbitmqctl reset sudo rabbitmqctl join_cluster rabbit@amq-node-1 sudo rabbitmqctl start_app为什么必须先stop_app?因为join_cluster本质上是把一个正在运行的 RabbitMQ 应用停掉后,在 Erlang 层面加入另一个节点。如果不停止应用,它当前持有的队列元数据会和新集群不一致,很容易出现节点状态混乱。
reset这一步要谨慎,它会把当前节点已有的全部数据清空。只有新节点加入集群时才需要,生产环境对已有数据的老节点千万别随手 reset。
加入完成后,在任意节点查看集群状态:
sudo rabbitmqctl cluster_status看到两个running节点,都标记为disc,集群基本就绪。这里多说一句:RabbitMQ 集群节点有 disk 和 ram 两种模式,生产环境我建议全部用 disk 节点。RAM 节点虽然快,但重启后需要从磁盘节点同步元数据,出问题反而复杂。
3.3 镜像队列策略:一条命令全局生效
所谓镜像队列,是通过策略(policy)来声明的。策略可以匹配队列名称,也可以匹配所有队列。对全局生效的最简单配置是:
sudo rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic","ha-sync-batch-size":100}'逐项解释:
ha-all是策略名称,可以自定义,但建议让人一眼看懂含义。^是正则表达式,匹配所有队列名称。ha-mode设置为all,表示队列在每个节点上都保留副本。ha-sync-mode设置为automatic,表示新节点加入后自动同步队列数据,不需要手动干涉。ha-sync-batch-size控制在同步大批量消息时分批发送的大小,避免一次性同步把网络和内存打满。
我在生产环境用过最朴素的方式就是ha-mode: all。它简单粗暴,所有队列都做全节点镜像,缺点是每一条消息都要复制到每个节点,集群节点越多,写入放大越严重。一般两个节点时完全可接受,节点超过五个时就要仔细评估。
3.4 镜像同步也不是瞬间完成的
镜像队列里的消息先写入主副本,主副本再异步复制到镜像副本。如果生产者一次性灌入大量消息,副本同步可能需要一段时间。此时某个镜像副本节点宕机后恢复,它会先处于未同步状态,需要把缺失的消息补回来。
查看队列同步状态可以用:
sudo rabbitmqctl list_queues name messages policy slave_pids synchronised_slave_pids如果synchronised_slave_pids里的节点数和slave_pids一致,说明所有副本都已同步。如果不一致,就是还有镜像副本没有追上进度。
提示:不要等节点都宕机了才想起看同步状态。日常巡检应该把“副本是否全部同步”作为一条固定检查项。
4. Keepalived 负责“让入口不失效”:VIP 漂移配置关键点
4.1 VRRP 和 VIP 漂移的直观理解
Keepalived 做的事情可以这样类比:两台 HAProxy 都想当“入口接待”,但门口只有一个招牌。这台天天喊“我还在”,另一台接不到回信就立刻把招牌抢过来。
VRRP(虚拟路由冗余协议)在原理上就是两台机器定期互相发送通告报文。正常情况下优先级高的节点持有 VIP;它一旦失联或者主动降级,优先级低的节点经过几个通告周期后,会接管 VIP,并触发 ARP 通告,让同一个局域网内的客户端把流量切换到新的物理机器上。
4.2 健康检查脚本必须和 HAProxy 挂钩
Keepalived 本身可以只做“进程活着没有”的判断,但这里我建议把健康检查的粒度卡在 HAProxy 上,因为 VIP 的职责是保证 HAProxy 入口不消失。
脚本内容很简单:
#!/usr/bin/env bash if systemctl is-active --quiet haproxy; then exit 0 else exit 1 fi把脚本放到/etc/keepalived/check_haproxy.sh,给执行权限:
sudo chmod +x /etc/keepalived/check_haproxy.sh这个脚本的效果是:主节点上 HAProxy 挂了,Keepalived 就把自己的优先级降下去,VIP 漂移到备节点。备节点的 HAProxy 继续接收客户端流量,再转发到健康的 RabbitMQ 上。
为什么不直接检查 RabbitMQ 进程?因为 RabbitMQ 宕机时,如果 HAProxy 还活着,主节点根本不需要切换。HAProxy 会自动从后端列表里摘掉不健康的 RabbitMQ 节点,流量还是在的。反过来,如果 HAProxy 挂了才对 VIP 漂移有硬需求。
4.3 基于单播的 Keepalived 配置
很多云环境不支持组播,VRRP 默认走组播经常不生效,所以我建议直接用单播模式,配置更可控。
主备两个节点上的/etc/keepalived/keepalived.conf基本一样,差别只在priority。
global_defs { router_id amq_lb_1 } vrrp_script chk_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 timeout 2 rise 1 fall 2 weight -30 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 110 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 888888 } unicast_src_ip 192.168.56.11 unicast_peer { 192.168.56.12 } virtual_ipaddress { 192.168.56.100/24 dev eth0 label eth0:vip } track_script { chk_haproxy } }备节点上把router_id改成amq_lb_2,priority改成100,unicast_src_ip改成自己的 IP,unicast_peer填对方的 IP。
这里有几个细节必须说透:
- 两个节点都用
state BACKUP,不要用 MASTER。配合nopreempt,可以避免主节点恢复后立刻抢回 VIP 导致客户端连接二度抖动。 auth_pass在 Keepalived 里最多支持 8 位,超过可能出问题。weight -30表示健康检查失败后把当前优先级降低 30。主节点原始优先级 110 降到 80,低于备节点的 100,VIP 才会切换。
4.4 Keepalived 告警和脑裂处理
脑裂是 Keepalived 最常见的高危故障:两台机器同时认为自己是主节点,VIP 在两端都绑定,客户端流量被撕成两半。减少脑裂的办法:
- 使用单播通信,明确指定对端,避免组播被交换机隔离导致互相发现不到。
- 健康检查脚本不要做得太复杂,Keepalived 的脚本执行时间和超时会影响 VRRP 状态机稳定性。
- 部署完成后要专门做一次“拔主节点 HAProxy 服务”的演练,确认 VIP 能正常漂移。
如果业务真的很敏感,还应该在脚本里增加检查“自己是否持有 VIP”的逻辑,防止本地已经把 VIP 丢了,却在那边空转。
5. HAProxy 的负载均衡不是简单转发:配置与健康检查细节
5.1 AMQP 与管理台两份配置
HAProxy 的配置思路是:把 RabbitMQ 的两个常用端口分别定义成监听入口,一份是 5672 的 AMQP 数据流量,一份是 15672 的管理界面流量。
我推荐的/etc/haproxy/haproxy.cfg如下:
global maxconn 4096 defaults mode tcp timeout connect 5s timeout client 2h timeout server 2h frontend amqp_front bind *:5672 default_backend amqp_back backend amqp_back balance leastconn option tcp-check server amq-node-1 192.168.56.11:5672 check inter 5s fall 2 rise 2 server amq-node-2 192.168.56.12:5672 check inter 5s fall 2 rise 2 frontend mgmt_front bind *:15672 default_backend mgmt_back backend mgmt_back mode tcp balance first server amq-node-1 192.168.56.11:15672 check inter 5s fall 2 rise 2 server amq-node-2 192.168.56.12:15672 check inter 5s fall 2 rise 2AMQP 是 TCP 长连接协议,不是 HTTP,所以监听和转发都是mode tcp。千万不要按照 Web 负载均衡的习惯去配 HTTP 模式,那样会把 AMQP 二进制帧拆坏。
5.2 为什么用 leastconn 而不是 roundrobin
RabbitMQ 客户端通常建立一条 TCP 长连接,并在这条连接上复用很多 channel。如果按 roundrobin 轮询,新连接会轮流分配到不同节点,看似平均,实际上因为连接不会频繁断开,很长时间内负载分摊是固定的,可能出现某台节点被一条少数超高流量连接“绑死”的情况。
leastconn是动态选择当前连接数最少的节点,更适合 AMQP 这种长连接场景。管理界面流量不太需要负载均衡,用balance first固定走主节点即可。
5.3 健康检查的粒度怎么选
配置里的check inter 5s fall 2 rise 2表示每 5 秒做一次 TCP 连通检查,连续失败 2 次判定节点宕机,连续成功 2 次才恢复启用。
TCP 检查的意义在于:RabbitMQ 进程一旦卡死到不能接受新连接,端口检查就会失败,HAProxy 会把该节点摘除。如果节点能接受 TCP 连接但是 AMQP 握手要很久,那属于更病态的情况,需要更高级的脚本检查,可以在 HAProxy 的 backend 里配合option tcp-check和tcp-check expect来模拟 AMQP 协议探测。不过日常使用,TCP 检查已经能覆盖绝大多数故障。
5.4 长连接超时别设太短
HAProxy 默认的timeout client和timeout server是 10 秒左右,对 AMQP 长连接来说完全不够。RabbitMQ 客户端往往会保持连接几小时甚至几天,如果你在 HAProxy 上设了过短的超时,会出现莫名其妙的连接中断。
我直接把超时设为 2 小时。这里要注意:TCP 长连接不断开不代表业务不活跃,RabbitMQ 业务心跳是 AMQP 协议层的机制,与 HAProxy 的 TCP 超时没关系。如果客户端有心跳,2 小时足够让空闲连接活着;如果整个链路需要跨越特殊网络设备,可能还需要配合 TCP 层的 keepalive 设置。
6. 高可用验证剧本:停服务、断节点、丢队列都试一遍
6.1 故障前先确认基线
高可用做完不等于一定能用,必须做故障演练。演练前先确认几个状态:
# RabbitMQ 集群状态 sudo rabbitmqctl cluster_status # 队列副本同步状态 sudo rabbitmqctl list_queues name messages policy slave_pids synchronised_slave_pids # VIP 落在哪台 ip addr show eth0 | grep 192.168.56.100 # HAProxy 后端节点状态 echo "show stat" | socat stdio unix-connect:/var/run/haproxy/admin.sock如果队列没有开启镜像策略,policy字段会显示空,后面两个字段也不会正常出现。这时候回退到上一步检查策略是否真的生效。
我建议用一个临时队列验证:
sudo rabbitmqctl set_policy ha-test "^test\." '{"ha-mode":"all"}'然后创建test.demo队列,发送几条消息,观察slave_pids是否包含两个节点。
6.2 剧本一:停掉一个 RabbitMQ 节点
在 amq-node-1 上执行sudo systemctl stop rabbitmq-server。
此时期望发生:
- HAProxy 在 10 秒内把 amq-node-1 从 backend 摘掉。
- VIP 不漂移,因为 HAProxy 还活着,流量继续由 amq-node-2 承接。
- 生产者通过 VIP 发送消息,消息正常进入队列的镜像副本。
- 消费者通过 VIP 继续消费,旧连接如果正好连在 amq-node-1 上会断开,客户端重连后自动切到 amq-node-2。
用一段简单的 Python 脚本模拟生产端和消费端会直观很多:
import pika, time params = pika.ConnectionParameters( host="192.168.56.100", port=5672, credentials=pika.PlainCredentials("mquser", "mqpass"), heartbeat=60 ) while True: try: conn = pika.BlockingConnection(params) channel = conn.channel() channel.queue_declare(queue="demo.q", durable=True) channel.basic_publish( exchange="", routing_key="demo.q", body=f"msg-{time.time()}".encode(), properties=pika.BasicProperties(delivery_mode=2), ) print("send ok") conn.close() except Exception as e: print("send failed:", e) time.sleep(2)故障期间会看到部分发送失败或等待重试,恢复后继续发送。真正的关键是把“客户端自动重连”配置做好,RabbitMQ 客户端库一般都有自动恢复机制,要在生产端显式打开。
6.3 剧本二:停掉 HAProxy 进程
在持有 VIP 的节点上执行sudo systemctl stop haproxy。
Keepalived 脚本会在 2 秒内检测到 HAProxy 异常,随后把本节点优先级降低 30。备节点优先级变成最高的 100,开始接管 VIP。
期望结果:
- 在备节点上执行
ip addr show eth0,能看到 VIP。 - 客户端继续用
192.168.56.100:5672访问,新连接落到了备节点的 HAProxy。 - 备节点 HAProxy 的 backend 里,两个 RabbitMQ 节点都是 UP。
这个场景我反复演练过很多次。如果发现 VIP 漂移后客户端需要很久才能恢复,通常是 ARP 缓存问题。可以在 keepalived.conf 里加上garp_master_delay 1,让接管后立刻发送 ARP 通告。
6.4 剧本三:整机关机与恢复
把 amq-node-1 整体关机,此时 VIP 要漂移到 amq-node-2,HAProxy、RabbitMQ 全部由单节点支撑。整机恢复后,amq-node-1 的 RabbitMQ 服务自动启动,会重新加入集群,镜像副本会自动补齐。
这里要特别注意:如果节点 B 在节点 A 宕机期间持续积累了大量消息,而节点 A 恢复时出现短暂的“未同步副本”状态,需要给它时间追数据。不要一恢复就立刻大量生产,更不要在集群还在同步时强制 shutdown,否则可能造成镜像数据覆盖或者副本不一致。
6.5 数据一致性观察
演练结束后,务必要检查两次:
- 队列中的消息总数是否和故障前一致。
- 队列各镜像副本的
synchronised_slave_pids是否一致。
我实际遇到过一次消费者在故障恢复后收到重复消息的情况,原因不是 RabbitMQ 丢了消息,而是客户端代码在重连后重新发布,导致重复投递。高可用做到最后,数据链路的下游也需要配合做幂等处理。
7. 故障排查完整链路与后续维护经验
7.1 从“连不上”倒推:一条可复现的排查链路
客户端报connection refused时,不要一头扎进 RabbitMQ 日志,先按从外到内的顺序走:
- 检查 VIP 是否还在:
ip addr show eth0,确认 192.168.56.100 是否绑定在当前机器。 - 检查 VIP 能否 ping 通:
ping 192.168.56.100。不通,去看 Keepalived 日志和 VRRP 状态。 - 检查端口是否监听:
ss -lntp | grep -E "5672|15672"。如果监听正常,看是不是 HAProxy 负载已被打满。 - 检查 HAProxy 后端节点状态:通过 socat 查看
show stat,看 amq-node-1/2 是 UP 还是 DOWN。 - 如果后端节点 DOWN,去对应机器上检查 RabbitMQ 进程:
systemctl status rabbitmq-server。 - 进程活着但连接异常,继续看集群状态:
rabbitmqctl cluster_status,确认两个节点是否都在同一集群里。 - 集群正常但队列不可用,看队列镜像状态:
rabbitmqctl list_queues name slave_pids synchronised_slave_pids。 - 最后看系统层,磁盘空间、内存、文件描述符、网络是否丢包。
这套链路看起来笨,但能避免在一堆日志里空转。我见过太多人一上来就抓 RabbitMQ 日志,结果问题出在 Keepalived 的 VRRP 通告被防火墙挡了。
7.2 常见问题对照表
| 现象 | 根因 | 处理方案 |
|---|---|---|
| 集群 join 失败,报 cookie 错 | 各节点.erlang.cookie不一致 | 重新复制 cookie,重启 RabbitMQ |
| 集群节点经常掉线 | 主机名没有固定解析 | 修好/etc/hosts,确保短主机名点对点可达 |
| VIP 无法漂移 | 防火墙拦截 VRRP 组播 | 改用单播,或者放通 VRRP 协议 |
| HAProxy 显示后端 DOWN 但 RabbitMQ 正常 | 端口检查间隔太短或设备过载误判 | 调整inter、fall、rise参数 |
| 客户端断线严重 | HAProxy 超时时间设置过短 | 调大timeout client和timeout server |
| 队列副本不同步 | 镜像策略未生效或同步未完成 | 确认 policy 生效,等待自动同步完成 |
| 主节点恢复后连接抖动 | Keepalived 抢占导致 VIP 来回切换 | 两端都使用 BACKUP 状态 + nopreempt |
7.3 运维小经验:定期巡检与升级
这套环境搭完之后,我给自己定了一个固定巡检项:
- 每天看一眼
cluster_status,确认节点数没变化。 - 每周检查一次队列副本同步状态,重点关注长时间不消费的堆积队列。
- 每月做一次故障演练,停一个 RabbitMQ 节点、停一次 HAProxy,验证 VIP 漂移和客户端重连。
- 版本升级前,先在一个隔离环境跑一遍镜像队列的数据迁移,别直接在线上动 Erlang 版本。
另外,如果 RabbitMQ 版本是 3.8 以上,新项目可以优先考虑 quorum queue,它在数据一致性上比镜像队列更稳。存量系统如果已经大量使用镜像队列,不要为了追新技术而贸然迁移,先把 HAProxy、Keepalived、VIP 这条链路跑稳,再考虑队列类型演进。
这套组合我用了很长时间,最大的体会是:高可用从来不是某个组件单独给出来的,而是依赖入口、负载均衡、数据副本、客户端重连整个链路一起工作。所谓“高可用”,是每一层都做好自己的冗余,然后把故障演练当成例行公事,才能在真实故障来临时不慌。