RabbitMQ 队列之战:Classic 和 Quorum 的性能洞察

简介: RabbitMQ 是一个功能强大的消息代理,用于分布式应用程序间的通信。它通过队列临时存储消息,支持异步通信和解耦。经典队列适合高吞吐量和低延迟场景,而仲裁队列则提供高可用性和容错能力,适用于关键任务系统。选择哪种队列取决于性能、持久性和容错性的需求。

RabbitMQ 是一个功能强大且广泛使用的消息代理,它通过处理消息的传输、存储和交付来促进分布式应用程序之间的通信。作为消息代理,RabbitMQ 充当生产者(发送消息的应用程序)和使用者(接收消息的应用程序)之间的中介,即使在复杂的分布式环境中也能确保可靠的消息传递。

RabbitMQ 的核心组件之一是队列,消息在其中临时存储,直到被使用。队列在 RabbitMQ 的架构中起着关键作用,支持异步通信并将生产者和使用者解耦。这种解耦允许应用程序独立运行,从而提高可扩展性、弹性和容错能力。

了解 RabbitMQ 中不同类型队列的性能特征对于设计高效的系统架构至关重要。队列决定了消息的路由、存储和使用方式,从而影响吞吐量、延迟和持久性。

了解经典队列

RabbitMQ 中的经典队列是默认队列类型,旨在实现高吞吐量和简单性。它们遵循先进先出 (FIFO) 模型,其中消息按照接收顺序传送给使用者,从而确保可预测的消息流。Classic 队列广泛用于性能和速度比跨多个节点的容错和消息持久性更重要的场景。


image.png

Classic Queues 的主要功能

  • 单节点存储:Classic 队列存储在单个 RabbitMQ 节点上。消息不会在其他节点之间复制,从而使队列更快,但在节点发生故障时弹性较差。
  • FIFO 消息处理:消息按照其到达的顺序进行存储和使用,从而确保简单的处理模型,尤其是对于消息顺序很重要的任务。
  • 持久和非持久消息:Classic 队列可以将消息存储在内存中(瞬态)或磁盘(持久)中。持久性消息将保存到磁盘,确保在服务器重新启动或崩溃时消息不会丢失,尽管这会带来性能权衡。
  • 高吞吐量:Classic 队列针对速度进行了优化,可以以低延迟处理大量消息。它们最适合消息处理速度至关重要的应用程序,例如实时系统或日志聚合服务。
  • 单节点持久性:虽然 Classic 队列支持消息持久性,但它们缺乏跨节点复制。这意味着,如果托管队列的节点发生故障,持久消息将在节点恢复时继续存在,但没有内置冗余来继续跨其他节点进行操作。

Classic 队列的使用案例

  • 实时系统:Classic 队列非常适合需要高速消息处理的应用程序,例如游戏系统、流媒体平台或监控工具。
  • 无状态应用程序:不需要消息复制或跨节点高可用性的应用程序受益于 Classic 队列的简单性和性能。
  • 低延迟:对于需要最大限度地减少消息生成和使用之间的延迟的工作负载,经典队列提供低延迟消息传递。

了解 Quorum 队列

RabbitMQ 中的仲裁队列是一种更新的、高度可用的、具有容错能力的队列类型,专为需要强大的持久性保证和节点故障弹性的系统而设计。Quorum 队列利用 Raft 共识算法跨多个节点复制消息,确保即使在硬件或软件故障的情况下也能保持消息可用性。这使它们非常适合消息丢失或停机不可接受的关键应用程序。


Quorum 队列的主要功能

  • 领导-追随者复制:仲裁队列使用领导-追随者模型运行。每个 Quorum 队列都有一个负责处理传入消息的领导节点和多个复制领导消息的 follower 节点。此复制可确保数据冗余,只有在大多数节点 (仲裁) 确认复制后才会确认消息。
  • Raft 共识算法:Raft 算法保证了节点之间的一致性。当消息发送到仲裁队列时,它会被复制到关注者,只有在大多数 (仲裁) 关注者确认该消息后,它才会变为 “已提交”。这提供了强大的持久性保证,确保系统可以从故障中恢复而不会丢失数据。
  • 容错能力:Quorum 队列旨在承受节点故障。如果 Leader 节点崩溃,将使用 Raft 协议从从 Follower 中选出一个新的 Leader,从而允许消息处理继续进行,并将中断降至最低。这提供了高可用性,并使仲裁队列在分布式环境中具有弹性。
  • 消息持久性:默认情况下,仲裁队列中的所有消息都是持久性的,这意味着它们将写入磁盘并在多个节点之间复制。这可确保消息不会丢失,即使 RabbitMQ 集群遇到节点故障或重新启动也是如此。
  • 高可用性:Quorum 队列通过确保只要大多数节点正常运行,消息传输和使用就可以继续进行,从而优先考虑可用性。这使它们成为无法容忍停机或数据丢失的任务关键型系统的理想选择。
  • 无单点故障:与 Classic 队列不同,Classic 队列由于驻留在单个节点上而容易受到节点故障的影响,而 Quorum 队列通过在 RabbitMQ 集群中的多个节点之间分发消息来消除单点故障的风险。

仲裁队列的使用案例

  • 金融服务:处理交易、付款或敏感财务数据的系统受益于 quorum 队列提供的容错能力和消息持久性。这些系统无法承受丢失消息或经历停机的后果。
  • 任务关键型应用程序:需要持续运行时间且不能容忍消息丢失的应用程序,例如医疗保健系统、实时监控或工业控制系统,非常适合仲裁队列。
  • 分布式系统:在服务器可能发生故障的多节点或分布式环境中,仲裁队列可确保消息处理无缝继续,即使单个节点出现故障也是如此。

性能基准测试:Classic 与 Quorum

我们使用 RabbitMQ PerfTest 工具来评估经典队列和仲裁队列的性能。作为此分析的一部分,我们收集了三种不同场景的性能统计数据。每个场景都涉及发布者和使用者的不同组合,具有固定的消息大小和一致的 30 秒时间间隔。

经典队列性能

场景

发送速率 (MSG/S)

接收速率(MSG/S)

第 99 个百分位延迟(以微秒为单位)

场景 1 (1Publisher, 1Consumer)

13329

9897

20649010 微秒

方案 2 (1Publisher, 2Consumer)

14112

9573

21415269 微秒

方案 3(2Publisher、4Consumer)

21829

13577

27186651 微秒

平均值(全部)

16423

10349

23083643 微秒

仲裁队列性能

场景

发送速率 (MSG/S)

接收速率(MSG/S)

第 99 个百分位延迟(以微秒为单位)

场景 1 (1Publisher, 1Consumer)

9202

5581

37644181 微秒

方案 2 (1Publisher, 2Consumer)

10717

5368

29972278 微秒

方案 3(2Publisher、4Consumer)

13132

4505

32919489 微秒

平均值(全部)

11017

5151

33,511,316 微秒

从执行的测试中获得的见解

1. 吞吐量(发送和接收速率)

  • 经典队列:
  • 平均发送速率:16,423 msg/s(比 quorum 队列高 49%)
  • 平均接收速率:10349 msg/s(比 quorum 队列高 2 倍)
  • 仲裁队列
  • 平均发送速率:11,017 msg/s
  • 平均接收速率:5,151 msg/s

Classic 队列在发送和接收速率方面始终优于 Quorum 队列,在所有场景中都显示出更高的吞吐量。Quorum 队列虽然更具弹性,但吞吐量会下降,尤其是在接收速率方面。

2. 延迟

  • 经典队列
  • 平均第 99 个百分位延迟:2308 万微秒。- 延迟保持可控并持续扩展,即使负载较高(2 个生产者,4 个消费者)也是如此。
  • 仲裁队列:
  • 平均第 99 个百分位延迟:3351 万 μs。- 延迟始终比传统队列高 40-50%,在较高负载下会出现显著峰值。

由于复制和容错能力,仲裁队列会引入更多的延迟。对于低延迟至关重要的应用程序,经典队列是队列的明确选择。

3. 可扩展性

  • 经典队列
  • 随着负载的增加而线性扩展,在 1 个生产者/2 个消费者(场景 2)和 2 个生产者/4 个消费者(场景 3)的场景之间,发送和接收速率显着跳跃。
  • 仲裁队列
  • 在高负载下吞吐量不佳。在具有 2 个生产者和 4 个使用者的方案 3 中,仲裁队列仅显示发送速率略有增加,接收速率略有下降,这表明与传统队列相比可扩展性较差。

Classic 队列可以有效地扩展,而 Quorum 队列则随着添加更多的创建者和使用者而显示吞吐量回报递减和延迟增加。

做出正确的选择

在 RabbitMQ 中,在 Classic Queues 和 Quorum Queues 之间进行选择取决于您的系统在性能、持久性、容错能力和资源可用性方面的特定要求。

何时选择 Classic Queues

  • 高吞吐量和低延迟要求
  • 非关键应用程序
  • 单节点或低成本环境

何时选择 Quorum 队列

  • 高可用性和容错能力
  • 持久消息传递
  • 分布式系统
  • 任务关键型系统

Classic 队列和 Quorum 队列之间的权衡

方面

经典队列

仲裁队列

吞吐量

高吞吐量、低延迟

由于复制开销而降低吞吐量

耐久性

可选的单节点持久性

多节点复制的强大持久性

容错

有限(无复制,单节点故障影响)

高容错性(多节点复制)

可用性

取决于单节点可用性

通过自动领导者选举实现高可用性

资源使用情况

低(单节点,较少的磁盘和内存开销)

高(多个节点,较高的 CPU、内存、磁盘使用率)

延迟

低延迟(无复制)

由于 Raft 复制导致更高的延迟

用例

高性能、非关键应用程序

关键应用程序、高可用性、无消息丢失

详细信息源

在决定 RabbitMQ 的 Classic 队列和 Quorum 队列时,重要的是要认识到两者各有优缺点。最佳选择取决于系统的特定需求。归根结底,在 Classic 队列和 Quorum 队列之间进行选择是一个决定,它取决于您在性能和可靠性之间的特定权衡:这是关于在速度和持久性之间找到适当的平衡。通过了解每种类型的队列的执行方式,您可以设计符合您的目标的 RabbitMQ 设置,无论是效率、健壮性,还是两者兼而有之。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
6月前
|
消息中间件 Java Spring
SpringBoot实现RabbitMQ的简单队列(SpringAMQP 实现简单队列)
SpringBoot实现RabbitMQ的简单队列(SpringAMQP 实现简单队列)
53 1
|
2月前
|
消息中间件 JSON Java
|
2月前
|
消息中间件
rabbitmq,&队列
rabbitmq,&队列
|
2月前
|
消息中间件 JSON Java
玩转RabbitMQ声明队列交换机、消息转换器
玩转RabbitMQ声明队列交换机、消息转换器
84 0
|
3月前
|
消息中间件 存储 NoSQL
MQ的顺序性保证:顺序队列、消息编号、分布式锁,一文全掌握!
【8月更文挑战第24天】消息队列(MQ)是分布式系统的关键组件,用于实现系统解耦、提升可扩展性和可用性。保证消息顺序性是其重要挑战之一。本文介绍三种常用策略:顺序队列、消息编号与分布式锁,通过示例展示如何确保消息按需排序。这些方法各有优势,可根据实际场景灵活选用。提供的Java示例有助于加深理解与实践应用。
83 2
|
4月前
|
消息中间件 RocketMQ
MetaQ/RocketMQ 原理问题之当消费集群规模较大时,处理分配不到队列的Consumer的问题如何解决
MetaQ/RocketMQ 原理问题之当消费集群规模较大时,处理分配不到队列的Consumer的问题如何解决
|
4月前
|
消息中间件 Java Kafka
说说RabbitMQ延迟队列实现原理?
说说RabbitMQ延迟队列实现原理?
67 0
说说RabbitMQ延迟队列实现原理?
|
4月前
|
消息中间件 NoSQL 关系型数据库
【RocketMQ系列十三】RocketMQ的集群核心概念之消费重试&死信队列&幂等消息的出现以及处理
【RocketMQ系列十三】RocketMQ的集群核心概念之消费重试&死信队列&幂等消息的出现以及处理
129 1
|
5月前
|
消息中间件 存储 监控
RabbitMQ 死信队列
RabbitMQ的死信队列(DLQ)是存储无法正常消费消息的特殊队列,常见于消息被拒绝、过期或队列满时。DLQ用于异常处理、任务调度和监控,通过绑定到普通队列自动路由死信消息。通过监听死信队列,可以对异常消息进行补偿和进一步处理,提升系统稳定性和可维护性。
87 1
|
5月前
|
消息中间件
RabbitMQ配置单活模式队列
RabbitMQ配置单活模式队列
135 0