RabbitMQ和RocketMQ和Kafka的区别

文章导读
要把 RabbitMQ、RocketMQ、Kafka 分开,看三件事就够:消息被消费后能不能重读、投递是推还是拉、有没有原生延迟消息和事务消息。RabbitMQ 是带路由的消息代理,消息推给消费者、确认后删除,exchange 的路由能力是它的强项;Kafka 是分区日志,消费者按位点拉取,靠保留策略过期删除,吞吐上限最高但延迟消息、单条重试要自己补;RocketMQ 用队列加长轮询,原生带延迟消
📋 目录
  1. A 对比RocketMQ Kafka activitemq和RabbitMQ的区别和联系
  2. B RocketMQ和RabbitMQ和Kafka:各自站在什么位置
  3. C RocketMQ和RabbitMQ和Kafka:性能、成本、运维、上手四个口径分开比
  4. D RocketMQ和RabbitMQ和Kafka:什么情况选哪一边
  5. E RocketMQ和RabbitMQ和Kafka:一次能复现的对比做法
A A

要把 RabbitMQ、RocketMQ、Kafka 分开,看三件事就够:消息被消费后能不能重读、投递是推还是拉、有没有原生延迟消息和事务消息。RabbitMQ 是带路由的消息代理,消息推给消费者、确认后删除,exchange 的路由能力是它的强项;Kafka 是分区日志,消费者按位点拉取,靠保留策略过期删除,吞吐上限最高但延迟消息、单条重试要自己补;RocketMQ 用队列加长轮询,原生带延迟消息、事务消息、失败重试和死信队列,偏向交易类业务。ActiveMQ(5.x 与 Artemis 两条线)属于更早的 JMS 实现,除非老系统已绑定 JMS 接口,新选型一般不把它和上面三个放同一档比较。

落地顺序建议固定成四步:先核实组件与版本,再看消费模型能否满足重读、顺序、延迟的需求,然后用同一消息大小、同一确认级别、同一并发跑三十秒短压测,最后算规格成本和运维人力。三方默认的确认级别与批量策略不同,拿默认配置下的吞吐直接对比没有意义;延迟精度、事务语义这类能力差异大,要回到本地安装版本的参数名和文档确认,不能照搬别人的说法。

对比RocketMQ Kafka activitemq和RabbitMQ的区别和联系

这一步在真实排查里对应「先确认对面到底是哪个组件、哪个版本、哪种消费模型」。三者的参数名、监控项、连「积压」这个词的定义都不一样,组件认错,后面的比较全是空转。确认动作按下面顺序走,每条都给出可核对的位置。

  1. RabbitMQ:rabbitmqctl version 看版本,rabbitmqctl list_queues name type messages consumers 看队列类型(classic / quorum / stream)和消费者数;管理台 15672 的 Queues 页 Type 列是同一份信息。
  2. Kafka:kafka-broker-api-versions.sh --bootstrap-server 127.0.0.1:9092 确认 broker 可达与协议版本,kafka-topics.sh --describe 看 PartitionCount、ReplicationFactor、Isr。
  3. RocketMQ:sh bin/mqadmin clusterList -n 127.0.0.1:9876 看 broker 列表和版本列,topicStatus 看队列数与位点。
  4. ActiveMQ:activemq --version,或管理台 /admin 首页的 Broker 版本;5.x 和 Artemis 是两套实现,配置文件名与命令都不同,先分清再谈对比。
rabbitmqctl version
rabbitmqctl list_queues name type messages consumers
bin/kafka-broker-api-versions.sh --bootstrap-server 127.0.0.1:9092
bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --describe --topic bench
sh bin/mqadmin clusterList -n 127.0.0.1:9876
sh bin/mqadmin topicStatus -n 127.0.0.1:9876 -t bench

三者的联系在于都提供「生产者—主题/队列—消费者」这套抽象,都支持集群与持久化,都能做投递失败重试。区别集中在三处:确认粒度是单条 ack 还是位点提交,删除方式是消费即删还是按保留策略过期,以及是否内建延迟消息与事务消息。

RocketMQ和RabbitMQ和Kafka:各自站在什么位置

RabbitMQ 是「智能代理、笨消费者」的路线:路由、TTL、死信、优先级都放在 broker 里做。判断口径是看它是否真的靠 exchange 在分发,执行 rabbitmqctl list_exchanges name type,如果业务代码大量使用 topic 或 headers 类型的 exchange,说明你依赖的是它的路由能力,换成 Kafka 要自己写分发逻辑。另一个必须确认的点是队列类型,rabbitmqctl list_queues name type 里出现 quorum 才说明用了新版高可用队列。

Kafka 是分区日志:顺序只在分区内成立,消费进度由 consumer group 的 offset 决定,消息删不删和有没有被消费无关。判断口径是 kafka-configs.sh --describe --entity-type topics --entity-name bench 看 retention.ms / retention.bytes,以及 kafka-consumer-groups.sh --describe --group g 里的 LAG 列——LAG 是位点差,不是「队列里堆了多少条待办」。

RocketMQ 站在中间:topic 下分多个队列,NameServer 管路由,broker 负责存储与主从同步,延迟消息、事务消息(半消息加回查)、顺序消息、重试与 %DLQ% 死信都是内建能力。判断口径是 mqadmin consumerProgress -n 127.0.0.1:9876 -g 消费组 的 diff 列,以及 broker 配置里的 messageDelayLevel——4.x 是固定等级,延迟需求先确认落不落在这些档位上。

RocketMQ和RabbitMQ和Kafka:性能、成本、运维、上手四个口径分开比

性能口径的量法要写死:同一消息大小(比如 512 字节)、同一确认级别、同一并发、跑三十秒,看 broker 侧或压测工具自己的汇总,而不是客户端单条耗时。Kafka 用 kafka-producer-perf-test.sh 输出的 records/sec、MB/sec、avg latency;RabbitMQ 用 perf-test 镜像输出里的 sent/s 与 recv/s;RocketMQ 观察 mqadmin statsAll 与 topicStatus 的位点增长。确认级别不统一就不用比:Kafka 的 acks=1 与 acks=all、linger.ms、batch.size,RabbitMQ 的 publisher confirm 开关与 prefetch,RocketMQ 的同步发送与异步发送,任一项不同结论就会翻转。

RabbitMQ和RocketMQ和Kafka的区别

成本口径是「满足目标吞吐所需的最小规格 × 时长 + 存储 + 跨可用区流量」。核对位置在云厂商消息队列产品的实例规格说明页和购买页的规格下拉项,自建则按 broker 节点数 × 规格 + 磁盘容量算。注意 Kafka 的成本和分区数、保留时长强相关,RabbitMQ 和 disk 水位、队列数量相关,别拿单机单队列的测试结果直接换算成集群报价。

运维口径看的指标不同:RabbitMQ 关注内存水位与积压,rabbitmqctl status 里的 memory 与磁盘告警阈值、list_queues 的 messages 增长;Kafka 关注分区与副本,kafka-topics.sh --describe 的 Isr 列缩短、--under-replicated-partitions 有输出就是信号;RocketMQ 关注 NameServer 与 broker 的存活、commitlog 落盘磁盘余量、主从同步状态,用 mqadmin clusterList 的地址与版本列逐台核对。

上门口径最容易被忽略。RabbitMQ 概念多(vhost、exchange、binding、queue),Kafka 概念少但消费者组重平衡和 offset 提交细节容易踩,RocketMQ 客户端 API 直观但部署组件多一层 NameServer。核对方式比较朴素:看官方 quickstart 从零到跑通要几步、docker images 里各自镜像多大、要起几个进程,再乘以团队里没接触过的人的学习时间。

RocketMQ和RabbitMQ和Kafka:什么情况选哪一边

  • 路由规则复杂、需要单条消息延迟或优先级、量在单机可控:选 RabbitMQ。前置条件是队列必须是 quorum 类型(3.8 以后才有),且队列数量不会快速膨胀到万级;验证方式是先按现有 routing key 结构在测试环境建一遍 exchange 和 binding,看管理台上队列数是否收敛。
  • 日志、埋点、变更事件流,需要重放历史、多个消费组各自独立进度:选 Kafka。前置条件是能接受只保证分区内顺序,且对磁盘和分区数有规划余量;验证方式是先用 kafka-consumer-groups.sh --reset-offsets --dry-run 模拟一次回溯,确认重放不会打垮下游。
  • 订单、支付、库存这类业务消息,需要本地事务与消息的最终一致、需要失败自动重试和死信:选 RocketMQ。前置条件是延迟精度需求落在该版本支持的档位内,并且团队接受 NameServer 加 Broker 的运维模型;验证方式是先建一个测试 topic 发一条事务消息,看回查日志和 %DLQ% 队列是否按预期出现。
  • 只是每秒几十条的内部通知,三者都能做,优先选团队已经在运维的那一套,为吞吐换栈通常不划算。

RocketMQ和RabbitMQ和Kafka:一次能复现的对比做法

十分钟版本的做法是:三个组件各起一个单机实例(镜像 tag 以本地 docker images 和镜像说明为准,不要照抄别人的启动参数),统一用 512 字节消息、单生产者单消费者、跑三十秒,只比同一份输出字段。

# Kafka:先建 topic,再压 30 秒左右(--throughput -1 表示不限速)
bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --create --topic bench \
  --partitions 3 --replication-factor 1
bin/kafka-producer-perf-test.sh --topic bench --num-records 200000 \
  --record-size 512 --throughput -1 \
  --producer-props bootstrap.servers=127.0.0.1:9092 acks=1 linger.ms=5 batch.size=16384

# RabbitMQ:用 perf-test 镜像,1 个生产者 1 个消费者 30 秒 512 字节
# 镜像名与版本以本机 docker images 结果为准
docker run --rm --network host <perf-test镜像> \
  --uri amqp://guest:guest@127.0.0.1:5672/%2f -x 1 -y 1 -z 30 -s 512

# RocketMQ:示例 benchmark 类在 example 模块,参数随版本变化,先看 jar 内类说明再执行
sh bin/tools.sh org.apache.rocketmq.example.benchmark.Producer
sh bin/mqadmin consumerProgress -n 127.0.0.1:9876 -g 压测消费组

预期差异要落在具体输出上:Kafka 的 perf 工具会直接打印 records/sec、MB/sec 和平均/最大延迟,加大 partitions 后这两项通常还会变;RabbitMQ 的 perf-test 输出 sent/s 与 recv/s,打开 publisher confirm 和持久化后这两项会明显下降;RocketMQ 没有统一的压测汇总,就要靠 topicStatus 的位点增长和 consumerProgress 的 diff 前后对比来估。这些方向性判断要用你自己环境的输出印证,别把别人的数字当结论。

最容易踩的坑是把不同语义的指标当成同一件事:拿 RabbitMQ 的 ready 消息数和 Kafka 的 LAG 直接比大小,前者是队列里还没投出去的消息,后者是已写入日志但消费位点没跟上,两者数量级接近只是巧合;另一个坑是压测时一边开了确认一边没开,或者把 --throughput 设成固定值再得出「性能差」的结论。对比前先把这两处对齐,再谈选型。