RabbitMQ版本升级调研

cuixiaogang

公司内部业务需要将RabbitMQ服务从3.6.16版本升级到4.1.1版本,需要梳理每个版本的主要升级内容,同时记录如何使用RabbitMQ4.1.1版本,以及升级过程中的注意事项。

基本信息

  • RabbitMQ4.1.1:2025年6月发布
  • RabbitMQ3.6.16:2018年6月发布

核心架构与存储系统

  • Khepri元数据存储:RabbitMQ 4.0 引入了 Khepri 作为新的元数据存储系统,替代了原有的 Mnesia。Khepri 基于 Raft 共识算法,显著提升了集群元数据的可靠性和管理效率,尤其在大规模集群中表现更稳定。
  • 经典队列镜像功能移除:4.0 版本彻底移除了经典队列的镜像功能(已被弃用多年),推荐使用Quorum 队列或 ** 流(Streams)** 实现高可用性。经典队列在 4.0 后变为非复制队列,需通过 Quorum 队列或流确保数据冗余。
  • Erlang 版本依赖升级:4.0 及以上版本要求 Erlang 26 或更高版本,而 3.6.16 依赖 Erlang 19-20。新 Erlang 版本带来了更好的并发性能和安全修复。

各版本的主要升级内容

  • 3.7版本
    • 引入的 Quorum队列 基于 Raft共识算法 ,通过多数派机制保证数据一致性,支持自动故障转移和毒消息处理。
  • 3.8版本
    • 引入实验性OAuth2插件
    • 支持TLSv1.3(Erlang 23+)
    • 支持单活跃消费者(Single Active Consumer),确保同一时间仅有一个消费者处理队列消息,提升可用性。
  • 4.0版本
    • 引入检查点(Checkpoint)机制,显著减少了Quorum队列在节点重启时的恢复时间。
    • 引入流(Streams),支持持久化、分区和高吞吐量的消息传递,适用于需要长期保留消息或高吞吐量的场景。
    • 改进了经典队列的存储引擎(CQV2),减少了大消息存储的磁盘占用,并优化了恢复时间。
    • AMQP 1.0设为核心协议,其实现效率大幅提升,峰值吞吐量较3.13.x版本提升超过两倍。
    • TLSv1.3(Erlang 23+)为默认启用,并改进了TLS配置的灵活性。
    • 开始跟踪客户端认证失败次数,并通过Prometheus指标和HTTP API暴露。
    • 移除了cluster_formation.randomized_startup_delay_range等过时配置,新增khepri相关配置。
    • 不再支持Erlang 21.3及以下,需更新客户端库(如 pika、amqp-client)。
    • 减少了节点启动时间(尤其是插件较多时),启动速度提升20-30%。
    • AMQP 1.0插件设为内置,无需手动启用。
    • 改进了TLS配置选项,支持证书链验证深度为零。
  • 4.1.1版本
    • 新增rabbitmq-queues force_checkpoint,用于强制Quorum队列生成检查点,同时清理磁盘段文件。
    • 新增/api/health/checks/ready-to-serve-clients,用于检查节点是否在连接数限制内并准备服务。
    • 优化了Quorum队列恢复机制,修复了集群形成期间的超时问题,并支持消费者优先级。
    • 优化了 OAuth2 插件的作用域变量支持
    • 优化了OAuth2插件的作用域变量支持(如x-vhost和sub参数),允许更灵活的权限控制,例如rabbitmq.write:*可动态匹配虚拟主机和用户。
    • 优化了 Shovel 插件的消息转换逻辑,支持复杂头信息处理。
    • 加快了空经典队列在干净关闭后的初始化速度。
    • 修复了AMQP 1.0客户端在高负载下的窗口大小负值问题。
    • 修复了TLS连接错误日志的缺失问题。
    • 修复了经典队列在高并发发布时的存储压缩滞后问题,以及消息路由到多个队列时的罕见异常。
    • 修复了流生产者在启用发布过滤时的异常问题。

PHP的使用推荐

依赖选择

特性 pecl-amqp(C 扩展) php-amqplib(纯 PHP)
安装方式 编译 C 扩展(依赖 rabbitmq-c) Composer 安装(无需编译)
性能 高(原生 C 实现) 较低(PHP 解释执行)
RabbitMQ 4.x 兼容性 不支持新特性(如 Quorum 队列) 支持(需 v3.x 版本)
PHP 版本依赖 1.9.4 支持 PHP 5.6~7.4 v3.x 需 PHP 7.2+
代码示例 $connection = new AMQPConnection(); use PhpAmqpLib\Connection\AMQPStreamConnection;

版本支持

RabbitMQ 版本 推荐客户端(优先) 推荐版本 支持的 PHP 版本 核心优势
3.6.16 php-amqplib ^2.12 5.6+ 兼容性好,无需编译
3.6.16 pecl-amqp 1.9.x 5.6-7.4 性能优于纯 PHP 实现
4.1.1 php-amqplib ^3.6 7.2+ 支持所有新特性,维护活跃
4.1.1 pecl-amqp ^2.0 7.4+ 高性能,适合高并发场景

RabbitMQ中的队列类型及特点

在 RabbitMQ 4.1.1 中,Classic Queue(经典队列)、Quorum Queue(仲裁队列)和Stream(流)是三种不同类型的消息存储和处理机制,它们在设计目标、可靠性、性能和适用场景上存在显著差异。

Classic Queue(经典队列)

核心特点

  • 存储机制:消息存储在单个节点上,支持镜像复制(Mirroring)到多个节点,但镜像机制已被弃用。
  • 一致性保证:弱一致性,镜像队列通过异步复制实现高可用,主节点故障时可能丢失未同步的消息。
  • 性能:低延迟,单节点处理效率高,但扩展能力有限。
  • 实现原理:基于 Mnesia 数据库(RabbitMQ 4.0 前的元数据存储系统),消息存储在内存或磁盘(取决于配置)。

优点

  • 低延迟:单节点处理,无需共识协议,适合对延迟敏感的场景。
  • 兼容性好:支持所有 RabbitMQ 版本,包括 3.6.x 及更早版本。
  • 简单易用:配置简单,无需复杂参数。

缺点

  • 可靠性低:镜像队列异步复制,主节点故障可能导致消息丢失。
  • 维护复杂:镜像队列管理复杂,故障恢复时间长。
  • 扩展性差:性能受限于单个节点,无法水平扩展。

适用场景

  • 非关键业务(如日志收集、通知推送)。
  • 对消息丢失容忍度高的场景。
  • 历史遗留系统,无法升级到新队列类型。

Quorum Queue(仲裁队列)

核心特点

  • 存储机制:基于 Raft 共识算法,消息同步复制到多数节点(通常 3-5 个),确保强一致性。
  • 一致性保证:强一致性,通过多数派确认(Quorum)确保消息不丢失。
  • 性能:中等延迟(比 Classic 高 20-30%),吞吐量取决于集群规模。
  • 实现原理:基于 Khepri 元数据存储系统(RabbitMQ 4.0 引入),支持自动故障转移和毒消息处理。

优点

  • 高可靠性:强一致性保证,主节点故障时不会丢失消息。
  • 自动恢复:支持自动故障转移,无需人工干预。
  • 简化运维:无需手动管理镜像,降低运维复杂度。

缺点

  • 更高延迟:需等待多数节点确认,延迟比 Classic 高。
  • 资源消耗大:至少需要 3 个节点,资源利用率低于 Classic。
  • 兼容性限制:仅支持 RabbitMQ 3.8+,客户端需支持扩展参数。

适用场景

  • 关键业务(如订单处理、支付系统)。
  • 对消息可靠性要求极高的场景。
  • 需要自动故障转移和简化运维的场景。

Stream(流)

核心特点

  • 存储机制:基于 Apache Kafka 类似的日志结构化存储,支持持久化、分区和高吞吐量。
  • 一致性保证:强一致性,通过 Raft 算法确保消息顺序和持久性。
  • 性能:极高吞吐量(百万级 TPS),低延迟(亚毫秒级)。
  • 实现原理:将消息追加到不可变日志文件,支持多消费者并行消费。

优点

  • 超高吞吐量:适合大数据、实时分析等高流量场景。
  • 长期存储:支持消息按时间或大小保留,无需手动清理。
  • 分区扩展:通过分区支持水平扩展,突破单机性能限制。

缺点

  • 高资源消耗:需要更多磁盘空间和内存。
  • API 限制:仅支持特定客户端 API,兼容性不如 Classic 和 Quorum。
  • 复杂性高:需要理解分区、偏移量等概念,学习成本较高。

适用场景

  • 高吞吐量数据流(如实时监控、IoT 数据采集)。
  • 需要长期保留历史消息的场景。
  • 需要分区并行处理的场景。

对比总结

特性 Classic Queue Quorum Queue Stream
一致性 弱一致性(异步复制) 强一致性(Raft 共识) 强一致性(Raft 共识)
可靠性 中等(可能丢失消息) 高(多数派确认) 高(持久化日志)
性能 低延迟,中等吞吐量 中等延迟,中等吞吐量 高吞吐量,低延迟
扩展性 单节点瓶颈 支持多节点,但受限于共识 支持分区水平扩展
消息保留 基于 ACK 或 TTL 基于 ACK 或 TTL 基于时间或大小
镜像管理 手动配置,复杂 自动管理,简单 自动管理,支持分区
适用场景 非关键业务,低延迟 关键业务,高可靠性 高吞吐量,长期存储

选型建议

  • 优先使用 Quorum Queue
    • 除非对延迟极其敏感(如高频交易),否则推荐使用 Quorum 替代 Classic,尤其是关键业务场景。
  • 使用 Stream 的场景
    • 当吞吐量需求超过 Quorum 的能力(如每秒百万级消息),或需要长期保留历史数据时,选择 Stream。
  • Classic Queue 的保留场景
    • 历史遗留系统,无法升级客户端。
    • 对延迟要求极高,且能容忍消息丢失的场景。
  • 混合部署策略
    • 关键业务用 Quorum,非关键业务用 Classic,高吞吐量场景用 Stream。
    • 例如:订单系统用 Quorum,日志收集用 Classic,实时监控用 Stream。

PHP示例

使用Quorum Queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Channel\AMQPChannel;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

// 声明Quorum队列
$channel->queue_declare(
'my_quorum_queue', // 队列名称
false, // passive
true, // durable
false, // exclusive
false, // auto_delete
false, // nowait
[
'x-queue-type' => ['S', 'quorum'] // 关键参数
]
);

使用Stream

1
2
3
4
5
6
7
8
9
10
11
12
13
// 声明Stream(需php-amqplib v3.6+)
$channel->queue_declare(
'my_stream',
false,
true,
false,
false,
false,
[
'x-queue-type' => ['S', 'stream'], // 关键参数
'x-max-length-bytes' => ['I', 1073741824] // 1GB存储限制
]
);