RabbitMQ 4.0:大声说俺中不中
RabbitMQ 4.0 是一个重要的版本更新,主要包括 AMQP 1.0 支持、流队列(Stream Queues)支、仲裁队列改进,去除经典队列的 v1 版本支持。在性能、安全和管理界面等方面进行了多项优化与改进。
本文将详细介绍 RabbitMQ 4.0 后新增以及改进的四种主要队列类型:
经典队列(Classic Queue) 仲裁队列(Quorum Queue) 流队列(Stream Queue) MQTT QoS 0 队列
📦 什么是 RabbitMQ 队列?
RabbitMQ 的队列本质上是一个 先进先出(FIFO)的消息缓冲区,用于临时存储生产者发送的消息,并由消费者依次消费。
根据生命周期和使用方式,RabbitMQ 队列可以分为以下几类:
接下来,我们深入探讨每种队列类型的实现原理和适用场景。
1️⃣ 经典队列(Classic Queue)
🧩 基本介绍
经典队列是 RabbitMQ 中的原始队列类型,它们使用非复制的 FIFO(先进先出)实现。
经典队列有两种实现(v1 和 v2)。这两个版本仅在数据在磁盘上的存储和检索方式上有所不同,但所有功能在两种实现中均可用。
经典队列用例
经典队列无需复制,非常适合对高可用性和数据安全性要求不高的应用。默认队列类型就是经典队列。
🔧 核心功能
✅ 支持消息和队列的 TTL(生存时间) ✅ 支持队列长度限制 ✅ 支持消息优先级和消费者优先级 ✅ 支持死信交换(DLX) ✅ 支持 QoS 预取控制 ✅ 支持独占队列
⚠️ 注意:全局 QoS 预取、v1 版本实现将在 RabbitMQ 4.0 被移除。
💾 存储实现
使用磁盘存储消息内容(消息体) 每个队列维护一个独立的索引文件,记录消息位置 v2 版本引入了“每个队列独立的小消息存储”,提升小消息处理效率
🎯 适用场景
对高可用性要求不高的任务分发系统 简单的微服务通信 不需要数据复制的轻量级队列场景
⚠️ 局限性
缺乏原生复制能力(需依赖镜像队列) 镜像队列存在性能瓶颈和同步阻塞问题 不支持消息重放
2️⃣ 仲裁队列(Quorum Queue)
🧩 基本介绍
RabbitMQ Quorum Queue 是一种现代队列类型,它基于 Raft 共识算法实现了持久、复制的 FIFO 队列。
RabbitMQ 中的 Quorum 队列旨在实现高可用性和数据安全性。它们在多个节点之间复制数据,以确保即使某些节点发生故障,消息也不会丢失。
仲裁队列用例
Quorum 队列非常适合那些不接受数据丢失的关键应用。它优先考虑容错能力和数据安全,而非 Classic 队列所具备的最低延迟和高级队列功能。
🔧 核心功能
✅ 数据复制(多节点同步) ✅ 持久化存储(始终启用) ✅ 支持死信交换(至少一次投递) ✅ 支持毒药消息(Poison Message)处理 ✅ 更好的故障恢复机制
💾 存储实现
使用预写日志(WAL)记录所有操作 日志条目同时写入内存和磁盘 达到一定大小后写入段文件并压缩 所有节点共享 WAL,保证一致性
🎯 适用场景
关键业务系统,如金融交易、订单处理等 对数据一致性、可靠性要求较高的场景 需要自动故障转移和数据恢复的环境
⚠️ 局限性
不支持 TTL、队列长度限制等高级特性 相比经典队列,延迟略高 不支持非持久或独占队列
3️⃣ 流队列(Stream Queue)
🧩 基本介绍
RabbitMQ 中的流队列是一种持久且可复制的数据结构,与传统队列类似,它缓冲来自生产者的消息,供消费者读取。流队列有两点不同:
生产者如何向他们写消息 以及消费者如何阅读他们发送的消息
Streams 的底层模型是一种不可变的仅追加日志。这意味着写入 Stream 的消息无法被擦除,只能被读取。要在 RabbitMQ 中读取 Stream 中的消息,需要一个或多个消费者订阅该 Stream,并根据需要多次读取同一条消息。
🔧 核心功能
✅ 持久化 + 复制(默认启用) ✅ 支持非破坏性读取(可重复消费) ✅ 高吞吐量(适用于大规模数据流) ✅ 内置惰性行为(消息直接写入磁盘) ✅ 支持保留策略(按时间或空间)
❌ 不支持:
TTL 或队列长度限制 独占或临时队列
💾 存储实现
使用固定大小的段文件(Segment Files)存储消息 每个段文件默认大小为 512MB 消息写入磁盘后建立索引,便于快速查找 支持高效的数据压缩和检索
🎯 适用场景
实时数据分析(如日志聚合、监控指标) 消息回溯(Replay)需求 高并发写入 + 多消费者订阅的场景 构建事件溯源(Event Sourcing)系统
4️⃣ MQTT QoS 0 队列
🧩 基本介绍
RabbitMQ 通过 MQTT 插件支持 MQTT 协议。默认情况下,MQTT 插件会创建经典队列,也可以配置为创建仲裁队列。
这些传统队列将数据写入磁盘,有时会跨节点复制数据,这可能会导致消息流瓶颈。在某些 MQTT 场景中,要求只需将消息发送给在线订阅者,而无需持久化和/或复制的开销。
这就引出了一个问题:我们如何才能消除这个瓶颈——我们能不能完全不使用队列?这正是 RabbitMQ 3.12 中引入 MQTT QoS 0 队列类型的原因。
与经典队列、仲裁队列和流不同,MQTT QoS 0 队列类型充当“伪”队列,这反而消除了底层队列进程。换句话说,它不作为单独的 Erlang 进程运行,也不将消息存储在磁盘上。相反,它使用订阅客户端的连接进程邮箱。
这意味着消息将直接发送到订阅客户端的 MQTT 连接进程,绕过传统的队列机制,确保立即送达任何“在线”的 MQTT 订阅者。这种方法显著降低了延迟和资源占用。
🔧 核心功能
✅ 极低延迟(无队列中转) ✅ 无需持久化或复制 ✅ 适用于扇出广播(一对多)场景 ✅ 资源占用极低
💾 存储实现
不使用磁盘存储 消息直接发送给在线订阅者的连接邮箱 不创建独立 Erlang 进程
🎯 适用场景
IoT 设备大规模广播通知(如固件更新) 临时性消息(可接受丢失) 对延迟敏感、但对可靠性要求较低的场景
⚠️ 局限性
不支持离线订阅者 无法持久化或重放消息 仅适用于 MQTT 协议
📊 四种队列类型对比总结
🧭 总结
如何选择合适的队列类型?
👨💻欢迎关注我的公众号「程序员wayn」,技术成长社群正招募热爱coding的你,加入我们,一起深入探讨技术、分享经验、共同成长!
作者原创技术好文推荐: