搜「RocketMQ和RabbitMQ和Kafka的区别」的人,通常已经卡在选型落地那一步:知道三者都是消息中间件,却不确定自己手里的业务该选哪个,或者团队已经选了一个,想确认有没有踩到不合适的边界。可以先用一句话对齐判断方向:RabbitMQ 按“消息被消费确认”路由,RocketMQ 和 Kafka 按“日志追加+位点提交”流转;先看你的消费语义是“确认即删除”还是“回放重放”,再看运维人力能不能扛住对应的部署形态,最后才比较吞吐。
三者最实用的区分口径不是吞吐数字,而是消费模型:RabbitMQ 是 broker 维护投递状态、ack 后出队,适合需要复杂路由、延迟消息、逐条确认的业务消息;Kafka 是分区日志、消费者自己提交 offset,适合高吞吐流式与回放;RocketMQ 更接近日志型但补齐了事务消息、延迟等级、按 tag 过滤等业务特性。选型前先用单机容器各起一个实例,用自己的消息大小和消费逻辑跑一轮,量出延迟与堆积恢复表现,再结合团队是否有专职中间件运维来定,不要只凭别人的压测表下结论。
RabbitMQ RocketMQ Kafka:各自站在什么位置
RabbitMQ 的定位是传统消息代理(broker),核心抽象是 exchange、queue、binding 和 routing key。生产者的消息先进 exchange,由绑定规则路由到一个或多个 queue,消费者从 queue 拉取或推送消费,ack 之后消息出队。这套模型擅长的是路由灵活:一个订单消息可以同时进库存队列、通知队列、审计队列,也能用 x-delayed-message 插件或延迟队列做定时投递。能核对的判断口径:在 RabbitMQ 官方文档的 Exchanges and Queues 章节看 exchange 类型列表(direct、topic、fanout、headers),再去管理插件的 Queues 面板看 messages ready / unacked 两个指标,就能判断消息是“等着被消费”还是“已投递未确认”。
Kafka 的定位是分布式提交日志。消息按 topic 分区、分区内有序追加,消费者用 offset 记录自己读到哪,broker 不跟踪单条消息是否被确认,只在 retention 策略下删除过期段。这套模型擅长的是高吞吐写入、多消费者各自按位点消费、以及消费历史数据(回放)。能核对的判断口径:在 Kafka 官方文档的 Topic Configs 里看 retention.ms、retention.bytes、segment.bytes 三个参数,它们直接决定你能回放多久、磁盘怎么涨;再看 consumer group 的 lag 指标(消费位点与日志末端位点的差值),这是判断积压最直接的数。
RocketMQ 的定位介于两者之间,模型上偏日志型(commitlog + consumequeue),但对业务场景做了补齐:支持事务消息(half message 加回查)、延迟消息(按延迟等级投递)、按 tag 和 key 过滤、消息轨迹查询。能核对的判断口径:在 RocketMQ 官方文档看延时消息的 delayLevel 配置项说明,以及事务消息的回查机制描述;管理端可以看 consumer 的堆积量(diff)与重试队列 %RETRY% 的消费情况。三个系统各自擅长的场景并不重叠:RabbitMQ 偏业务解耦和复杂路由,Kafka 偏数据管道和流处理,RocketMQ 偏交易类业务消息加可靠投递。
RabbitMQ RocketMQ Kafka:性能、成本、运维、上手四个口径分开比
性能怎么量:不要看二手压测表,用自己的消息大小和消费侧逻辑跑。可以用官方的压测工具,例如 Kafka 自带 kafka-producer-perf-test.sh 和 kafka-consumer-perf-test.sh,RabbitMQ 可用 rabbitmq-perf-test(Java 版),RocketMQ 自带 benchmark 工具(producer/consumer 两个子命令)。同一台机器、同一批消息体、同样的 ack 或提交方式,分别量写入吞吐、端到端延迟、以及消费端积压后恢复的速度。要点是消费侧是否批量、是否异步提交,这些参数对结果的影响往往超过中间件本身差异。
成本怎么量:成本分三块——机器资源、磁盘、人力。磁盘占用可以直接看:Kafka 按 retention 保留,磁盘预估约等于每日写入量乘以保留天数(可按 Topic Configs 的 retention.bytes 上限核对);RabbitMQ 队列有长度或内存水位限制,超出会触发流控,管理面板的 memory / disk free 指标和 vm_memory_high_watermark 参数可以核对;RocketMQ 的 commitlog 默认保留时长看 fileReservedTime,约定期清理。人力成本体现在部署形态上:RabbitMQ 通常单节点或镜像队列集群起步,Kafka 与 RocketMQ 常需要多节点加协调组件(Kafka 依赖或内嵌 KRaft/ZooKeeper,RocketMQ 有 NameServer 加 Broker 主从),运维投入要按团队实际能力估,不建议只看一台单机的内存占用下结论。
运维怎么量:RabbitMQ 管理插件面板直接看 connections、channels、queues、messages ready/unacked、节点内存与磁盘告警;Kafka 看 broker 的 under-replicated partitions、consumer group lag、磁盘使用率,可用 kafka-consumer-groups.sh --describe 列出每个分区的 lag;RocketMQ 看 broker 的堆积量、%RETRY% 重试队列、以及 NameServer 的注册状态。三个系统的高频故障点也不同:RabbitMQ 常见的是队列堆积触发内存流控导致连接被阻塞,Kafka 常见的是分区热点与磁盘写满,RocketMQ 常见的是消费堆积和重试队列被拖慢。
上手怎么量:RabbitMQ 概念最少(exchange、queue、ack),一个 Spring Boot 或 Python 的 pika 客户端几十行能跑通;Kafka 要理解分区、offset、消费者组、rebalance,概念多但资料多;RocketMQ 概念数量居中,但事务消息、延迟等级、tag 订阅这些特性需要读完文档才用得对。衡量标准可以很朴素:让团队里没接触过该中间件的一位同学,按官方 Quick Start 在半天内跑通生产消费并改通一个业务示例,看卡在哪一步。这一步的卡点通常就是后续运维的成本来源。

RabbitMQ RocketMQ Kafka:什么情况选哪一边
场景一:业务系统之间解耦,一个事件要分发给多个下游,且需要延迟消息或死信处理。前置条件是消息量在单队列可承受范围内、允许每条消息被 ack 后出队、团队能维护一个 broker 集群。这种场景优先 RabbitMQ,用 topic exchange 做路由、用死信队列兜住消费失败的消息。验证方式是先在测试环境跑一遍路由规则,看管理面板里各队列的 ready 数是否符合预期,失败消息是否落进死信队列。
场景二:日志、埋点、变更事件需要高吞吐写入,且下游要能回放历史数据,或者多个消费组各自按自己的节奏消费。前置条件是能接受分区内有序而全局无序、能接受消费位点由消费端管理、有磁盘容量规划能力。这种场景优先 Kafka,用分区数和副本数来平衡吞吐与可用性,用 retention 控制可回放窗口。验证方式是故意停掉一个消费组一段时间,再用 kafka-consumer-groups.sh --describe 看 lag 增长,恢复后确认能从原 offset 继续读,数据不丢。
场景三:交易、订单、支付类业务消息,既要可靠投递,又用到事务消息、延迟等级、按 tag 过滤这些特性。前置条件是团队接受部署 NameServer 加 Broker 的形态、能维护多节点集群、业务侧愿意按 RocketMQ 的消息模型改写。这种场景可以优先 RocketMQ。验证方式是发一条事务消息,在事务未提交前查消费端是否看不到,提交后确认能消费到,再检查重试队列是否按预期接收失败消息。如果以上前置条件不成立,退回 RabbitMQ 也完全可行,不要为了特性迁就架构。
RabbitMQ RocketMQ Kafka:一次能复现的对比做法
十分钟能跑完的做法是:用 Docker 各起一个单节点实例,用同一段脚本分别发固定数量的相同大小消息,对比消费延迟和积压表现。先起三个容器(端口错开,命令可直接复制):
docker run -d --name mq-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
docker run -d --name mq-kafka -p 9092:9092 -e KAFKA_NODE_ID=1 -e KAFKA_PROCESS_ROLES=broker,controller -e KAFKA_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 -e KAFKA_CONTROLLER_QUORUM_VOTERS=1@localhost:9093 -e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 apache/kafka:latest
docker run -d --name mq-rocket -p 9876:9876 -p 10911:10911 apache/rocketmq:latest sh mqnamesrv接着用任意一种客户端(Python 的 pika、kafka-python,或 RocketMQ 的 Java 客户端)写同一逻辑:发 1 万条 1KB 消息,记录从发送完成到消费完成的总耗时;再停掉消费者 30 秒后恢复,观察积压消化速度。RabbitMQ 通过管理面板的 messages ready 曲线看积压,Kafka 用 kafka-consumer-groups.sh --describe 看 LAG 列,RocketMQ 看消费者 diff 指标。预期输出差异在:Kafka 在批量发送下吞吐通常更高、恢复后按 offset 继续读;RabbitMQ 单条 ack 模式下延迟更稳定,但积压大时受流控影响明显;RocketMQ 的延迟消息和事务消息在这个简单脚本里体现不出来,需要单独验证。
这里最容易踩的坑是拿默认配置横向对比:Kafka 的生产者默认 batch 和压缩与 RabbitMQ 的逐条发布根本不是一个量级,RocketMQ 的刷盘方式(同步刷盘还是异步刷盘)也直接改变延迟曲线。对比时要显式写出参数,比如 Kafka 生产者设置 acks=all、batch.size=16384、linger.ms=5,RabbitMQ 关闭自动 ack 用逐条确认,RocketMQ 记录 broker 的 flushDiskType。另一个坑是容器单节点没有副本,测出的可用性结论不能外推到集群形态。所有测出的数字只在本机、本版本、本组参数下有效,换机器或换版本都要重跑,不要把它当成通用性能表引用。