RabbitMQ 4.0 是一个重要的版本更新,主要包括 AMQP 1.0 支持、流队列(Stream Queues)支、仲裁队列改进,去除经典队列的 v1 版本支持。在性能、安全和管理界面等方面进行了多项优化与改进。
本文将详细介绍 RabbitMQ 4.0 后新增以及改进的四种主要队列类型:
- 新增经典队列(Classic Queue)v2 版本
- 新增仲裁队列(Quorum Queue)
- 新增流队列(Stream Queue)
- MQTT QoS 队列插件
📦 什么是 RabbitMQ 队列?
RabbitMQ 的队列本质上是一个 先进先出(FIFO)的消息缓冲区,用于临时存储生产者发送的消息,并由消费者依次消费。
根据生命周期和使用方式,RabbitMQ 队列可以分为以下几类:
- 持久队列:只要不手动删除,就会一直存在,数据会保存到磁盘上,适合重要数据的存储。
- 临时队列:服务运行时存在,服务停止就消失,常用于临时任务处理。
- 自动删除队列:当最后一个消费者断开连接后,会自动 “消失”,可根据需求配置。
1️⃣ 经典队列(Classic Queue)
🧩 基本介绍
经典队列是 RabbitMQ 中的原始队列类型,它们使用非复制的 FIFO(先进先出)实现。
经典队列有两种实现(v1 和 v2)。这两个版本仅在数据在磁盘上的存储和检索方式上有所不同,但所有功能在两种实现中均可用。
经典队列用例
经典队列无需复制,非常适合对高可用性和数据安全性要求不高的应用。默认队列类型就是经典队列。
🔧 核心功能
- 消息和队列生存时间(TTL):可以设置消息在队列中保留多久,或者队列本身的存活时间。
- 队列长度限制:避免队列无限增长,占满服务器空间。
- 消息和消费者优先级:重要的消息或者消费者可以优先处理。
- 死信交换(DLX):处理无法正常消费的 “死信” 消息。
- QoS 预取控制:控制消费者一次能获取多少消息,防止消费者过载。
- 独占队列:仅供特定连接使用的队列。
⚠️ 注意:全局 QoS 预取、v1 版本实现将在 RabbitMQ 4.0 被移除。官方在4.0 之后默认使用 v2 版本作为经典队列得唯一实现。v2 版本对比 v1 版本,有更高的吞吐量和更低的延迟。
💾 存储实现
- 使用磁盘存储消息内容(消息体)
- 每个队列维护一个独立的索引文件,记录消息位置
- v2 版本引入了“每个队列独立的小消息存储”,提升小消息处理效率
🎯 适用场景
经典队列适合对数据安全和高可用性要求不高的场景。比如一些小型的后台任务分发系统,或者简单的微服务之间的通信,像小商店的订单处理系统,偶尔丢几个订单影响不大,就可以用经典队列。
⚠️ 局限性
-
自身没有数据复制功能,需要借助镜像队列实现,而镜像队列存在性能和同步问题。
-
不支持消息重放,比如消息消费失败后,不能重新获取处理。
2️⃣ 仲裁队列(Quorum Queue)
🧩 基本介绍
仲裁队列基于 Raft 共识算法,实现了数据的持久化和多节点复制,就像给消息找了多个 “备份仓库”,即使部分节点故障,消息也不会丢失。
仲裁队列用例
Quorum 队列非常适合那些不接受数据丢失的关键应用。它优先考虑容错能力和数据安全,而非 Classic 队列所具备的最低延迟和高级队列功能。
🔧 核心功能
-
数据复制:在多个节点间同步消息,保障高可用性。
-
持久化存储:数据默认保存到磁盘。
- 死信交换:确保消息至少被投递一次。
- 毒药消息处理:能识别并处理那些导致消费失败的异常消息。
- 故障恢复:具备强大的故障恢复机制。
💾 存储实现
- 使用预写日志(WAL)记录所有操作
- 日志条目同时写入内存和磁盘
- 达到一定大小后写入段文件并压缩
- 所有节点共享 WAL,保证一致性
🎯 适用场景
在金融交易、订单处理等关键业务系统中,数据绝对不能丢失,仲裁队列就是最佳选择。比如银行转账系统,每一笔转账记录都必须安全可靠。
⚠️ 局限性
- 不支持 TTL、队列长度限制等高级特性
- 相比经典队列,延迟略高
- 不支持非持久或独占队列
3️⃣ 流队列(Stream Queue)
🧩 基本介绍
流队列也是持久且可复制的,但它和传统队列在消息读写方式上有所不同。它的底层就像一本只能追加内容、不能删除内容的日志,消息写入后可以被多次读取。
Streams 的底层模型是一种不可变的仅追加日志。这意味着写入 Stream 的消息无法被擦除,只能被读取。要在 RabbitMQ 中读取 Stream 中的消息,需要一个或多个消费者订阅该 Stream,并根据需要多次读取同一条消息。
🔧 核心功能
- 持久化和复制:默认开启,保障数据安全。
- 非破坏性读取:消息可以被多次消费,不会被删除。
- 高吞吐量:能快速处理大规模数据。
- 内置惰性行为:消息直接写入磁盘,减少内存压力。
- 保留策略:可以按时间或空间设置消息保留规则。
局限性
- 不支持 TTL、队列长度限制。
- 不支持独占或临时队列。
💾 存储实现
- 使用固定大小的段文件(Segment Files)存储消息
- 每个段文件默认大小为 512MB
- 消息写入磁盘后建立索引,便于快速查找
- 支持高效的数据压缩和检索
🎯 适用场景
- 数据分析:比如收集和分析服务器日志、监控系统指标。
- 消息回溯:需要重复读取消息进行处理的场景。
- 高并发写入和多消费者订阅:像大型电商的促销活动,瞬间大量订单消息涌入,多个系统同时处理。
- 构建事件溯源系统:记录系统所有操作事件,方便追溯。
4️⃣ MQTT QoS 队列
🧩 基本介绍
RabbitMQ 通过 MQTT 插件支持 MQTT 协议。在一些 MQTT 场景中,不需要消息持久化和复制,只希望消息快速发给在线订阅者,MQTT QoS 队列就应运而生。它不像传统队列那样作为独立进程运行,也不把消息存到磁盘,而是直接将消息发送到订阅客户端的连接进程邮箱。
🔧 核心功能
- 极低延迟:消息不经过队列中转,直接送达。
- 无需持久化或复制:减少资源消耗。
- 适用于扇出广播:一对多的消息发送场景。
- 资源占用极低:节省服务器资源。
💾 存储实现
- 不使用磁盘存储
- 消息直接发送给在线订阅者的连接邮箱
- 不创建独立 Erlang 进程
🎯 适用场景
- 实时数据分析:比如收集和分析服务器日志、监控系统指标。
- 消息回溯:需要重复读取消息进行处理的场景。
- 高并发写入和多消费者订阅:像大型电商的促销活动,瞬间大量订单消息涌入,多个系统同时处理。
- 构建事件溯源系统:记录系统所有操作事件,方便追溯。
⚠️ 局限性
- 只支持在线订阅者,离线设备收不到消息。
- 消息不能持久化,也无法重放。
- 仅适用于 MQTT 协议。
📊 四种队列类型对比总结
四种队列类型对比总结
| 功能 / 特性 | 经典队列 | 仲裁队列 | 流队列 | MQTT QoS 0 队列 |
|---|---|---|---|---|
| 是否持久化 | 可选 | 默认持久化 | 默认持久化 | 不持久化 |
| 是否复制 | 需镜像 | Raft 复制 | 分布式复制 | 否 |
| 是否支持重放 | 否 | 否 | 支持多次读取 | 否 |
| 是否支持 TTL | 是 | 否 | 否 | 否 |
| 是否支持优先级 | 是 | 否 | 否 | 否 |
| 吞吐量 | 中等 | 中等 | 高吞吐 | 极高(无持久) |
| 适用场景 | 微服务通信、后台任务 | 金融交易、关键系统 | 实时日志、事件溯源 | IoT 广播、低延迟推送 |
🧭 总结
如何选择合适的队列类型?
- 快速部署、简单易用:经典队列
- 高可用、强一致性:仲裁队列
- 高吞吐、支持消息重放:流队列
- MQTT 场景、低延迟、无需持久化:MQTT QoS 0 队列
- 大规模广播、IoT 场景:MQTT QoS 0 队列
- 构建事件溯源、实时分析平台:流队列
- 对数据一致性要求极高:仲裁队列
- 不需要队列持久化、追求极致性能:MQTT QoS 0 队列
通过了解这四种队列类型的特点和适用场景,我们就能在实际项目中根据需求灵活选择,充分发挥 RabbitMQ 的强大功能。