Appearance
RabbitMQ 仲裁队列
1. 简介
仲裁队列(Quorum Queue)于 3.8 版本引入,是一种高可用、分布式、容错能力强的队列实现,是为了替代经典队列(Classic Queue)的镜像队列模式而设计的。它使用 Raft 共识算法来确保消息的高可靠性,适合需要高可用性和强一致性的场景。
2. 配置仲裁队列
仲裁队列不是默认队列类型,需要在创建时显式指定。
通过命令行创建:
Bashrabbitmqadmin declare queue name=quorum-queue type=quorum通过 RabbitMQ 配置文件(
rabbitmq.conf)定义:Propertiesdefault_queue_type = quorum
Note:配置副本数量
副本数量决定了仲裁队列的冗余程度,通常设置为 3 或 5(建议奇数)。可以通过
x-quorum-initial-group-size参数指定:Bashrabbitmqadmin declare queue name=quorum-queue type=quorum arguments='{"x-quorum-initial-group-size": 3}'
3. 仲裁队列与镜像队列的差异
性能
镜像队列:镜像队列包含一个主队列和多个从队列,当生产者向主队列发送一条消息,主队列会将消息同步给从队列,所有的从队列都保存消息后,主队列才会向生产者发送确认。
仲裁队列:仲裁队列的算法是基于 Raft 共识算法的一个变种,提供更好的消息吞吐量。仲裁队列包含一个主副本和多个从副本,当生产者向主副本发送一条消息,主副本会将消息同步给从副本,超过半数的副本保存消息后,主副本才会向生产者发送确认。这意味着少部分比较慢的从副本不会影响整个队列的性能。同样地,主副本的选举也需要超过半数的副本同意,这会避免出现网络分区时,队列存在 2 个主副本。由此可见,仲裁队列相对于可用性更看重一致性。
故障恢复
镜像队列:使用集群部署时,如果其中一个节点故障下线,待它消除故障重新上线后,它保存的所有从队列的数据都会丢失。此时运维人员需要选择是否同步主队列的数据到从队列中,如果不同步数据,会增加消息丢失的风险。如果同步数据,同步时队列是阻塞的,无法对其进行操作。当队列中存在大量堆积消息时,同步会导致队列几分钟、几小时或者更长时间不可用。
仲裁队列:使用集群部署时,如果其中一个节点故障下线,待它消除故障重新上线后,它保存的数据不会丢失,主副本会直接从从副本中断的地方开始复制消息。复制的过程是非阻塞的,整个队列不会因为新的副本加入而受到影响。
网络分区处理策略
镜像队列:通过
cluster_partition_handling配置项决定网络分区时的处理策略。仲裁队列:依赖 Raft 算法,多数派(包含 Leader 的分区)继续提供服务,少数派停止服务,直到网络恢复。
消息优先级
镜像队列:支持。
仲裁队列:不支持消息优先级。这是因为消息优先级的实现需要队列在投递消息时动态调整消息顺序,而仲裁队列的底层基于 Raft 共识算法来实现消息复制和一致性。这种机制会将消息写入日志文件,并在节点之间复制,因此动态调整顺序的复杂性与性能代价较高,因此未实现消息优先级支持。
惰性模式
镜像队列:支持。
仲裁队列:不直接支持,但消息存储机制天然具有类似惰性模式的效果。惰性模式的目的是将消息尽可能存储在磁盘上,而不是保留在内存中,以节省内存资源。在仲裁队列中,所有消息默认是写入磁盘的,因为它的设计目标是确保消息的可靠性和高可用性。仲裁队列的存储机制天然满足类似惰性模式的目标,但它不是通过启用惰性模式来实现的,而是通过其日志持久化机制实现的。