跳到正文

Kafka vs RocketMQ ​

一句话:两者都是「分区日志 + 副本」,差别在存储单元的粒度;选型不是比功能清单,而是看消息形态、Topic 规模、团队运维能力和生态依赖。

适用版本:Kafka 3.9(最后一个支持 ZooKeeper 的版本)/ 4.0(仅 KRaft);RocketMQ 4.9 / 5.3 / 5.5。跨版本结论必须标版本,否则很容易拿 4.x 的印象评价 5.x。

为什么需要 ​

两个系统都能做到「高吞吐、可持久化、多副本」,但它们的存储单元不同,导致同一组需求下的成本结构不同:

  • 日志采集:Topic 少、单 Topic 流量大、下游是 Flink/Spark。
  • 业务消息:Topic 多、单 Topic 流量小、需要延迟/事务/过滤/死信。

把这两类负载放到同一个系统上,通常不是不能跑,而是某一侧的运维成本会被放大。选型要回答的是「哪一侧的成本你更愿意承担」。

核心机制 ​

存储模型:Partition 日志 vs 统一 CommitLog ​

Kafka:每个 Partition 是一条独立的日志目录,包含多个 Segment(.log、.index、.timeindex)。Partition 既是并行单位,也是副本单位;Leader 负责读写,Follower 拉取。

RocketMQ:所有 Topic 的消息写同一份 CommitLog,每个 Queue 只有一份 20 字节条目的 ConsumeQueue 索引;Queue 是逻辑并行单位,副本单位是 Broker 上的 CommitLog 文件。

由此产生的差异:

维度KafkaRocketMQ
单 Topic 吞吐高,Partition 并行 + sendfile高,CommitLog 顺序写
Topic/Partition 数量大文件与元数据压力大,故障恢复慢统一日志,Topic 数量压力小
读路径直接按 Partition offset 读日志先读 ConsumeQueue 再读 CommitLog
零拷贝消费转发可用 sendfile,拷贝更少写入用 mmap,读取仍经 PageCache
单分区故障恢复以 Partition 为单位以 Broker 的 CommitLog 为单位

RocketMQ 的统一 CommitLog 不是「免费」的:每个 Queue 仍有 ConsumeQueue 文件,万级 Topic × 每 Topic 多 Queue 依然是大量小文件,需要调大 PageCache 和文件句柄。它解决的是「每个 Topic 一套独立日志」的问题,不是「无限 Topic」。

副本与选主 ​

维度KafkaRocketMQ
副本集合ISR(Leader 维护的同步副本集合)经典主从:固定 Master/Slave;DLedger:Raft 多数派;5.x:Controller 的 SyncStateSet
写入确认acks=all 等 ISR 全部写入SYNC_MASTER 等 Slave 确认;DLedger 等多数派
选主KRaft Controller(4.0 唯一模式)4.5+ DLedger 自动选主;5.x Controller 自动选主
已提交消息会丢吗acks=all + min.insync.replicas>=2 + 不开 unclean 时不丢同步复制 / 多数派确认后不丢

Kafka 的 ISR 不是「最终一致」:它是 Leader 认可的法定确认集合,acks=all 下写入要等 ISR 全员。ISR 可以缩到只剩 Leader,这时 acks=all 等价于 acks=1,所以必须配 min.insync.replicas 和 unclean.leader.election.enable=false。

能力差异(按版本) ​

能力Kafka 3.9 / 4.0RocketMQ 4.9RocketMQ 5.x
延迟消息无 Topic 级原生延迟,需外部调度或应用层实现18 个固定级别Timer 时间轮,任意时间点,受 timerMaxDelaySec 上限约束
事务事务 API,支持 Kafka 读写链路内的 EOS(read_committed)半消息 + 回查半消息 + 回查
顺序Partition 内有序Queue 内有序Queue / LiteTopic 内有序
Broker 端过滤无 Tag/SQL 过滤,消费端自行过滤Tag / SQL92Tag / SQL92
死信队列无内置 DLQ,需应用实现内置 %DLQ%内置 %DLQ%
消息轨迹无内置可开 traceTopicEnable可开,另有 OpenTelemetry 接入
多语言接入原生协议生态广Remoting(Java 为主)Remoting + gRPC/HTTP Proxy,另有 Pop 消费
超大规模会话通道需大量 Topic/Partition不支持5.5 LiteTopic

事务消息不是 RocketMQ 独有:Kafka 有事务 API,Pulsar、RabbitMQ、QMQ 也有各自的实现。准确说法是「RocketMQ 的半消息 + 回查模型适合业务侧本地事务与消息发送的最终一致」,而不是把它说成独有能力。

运维成本 ​

  • Kafka:3.9 之前要维护 ZooKeeper 或 KRaft Controller;4.0 只剩 KRaft,元数据在内部日志里。分区重分配、副本迁移、Controller 选举都有成熟工具,但参数多,调优门槛高。
  • RocketMQ:NameServer 极简,Broker 参数相对少;5.x 多了 Proxy、Controller 等组件,部署形态更丰富,也意味着更多选择。DLedger / Controller 的引入提高了高可用能力,同时增加了节点数和运维面。
  • 托管服务:云上的 Kafka/RocketMQ 都会隐藏底层差异,选型时要看具体产品的版本、配额和限制,不能直接套开源结论。

最小上手 ​

选型前先做一次 10 分钟的现状盘点,而不是先跑 benchmark:

bash
# Kafka:Topic 数、Partition 数、ISR 是否完整、消费积压
bin/kafka-topics.sh --bootstrap-server broker:9092 --list | wc -l
bin/kafka-topics.sh --bootstrap-server broker:9092 --describe | head -50
bin/kafka-consumer-groups.sh --bootstrap-server broker:9092 --describe --group g1

# RocketMQ:Topic 数、队列分布、消费积压
sh bin/mqadmin topicList -n namesrv:9876 | wc -l
sh bin/mqadmin clusterList -n namesrv:9876
sh bin/mqadmin consumerProgress -n namesrv:9876 -g g1

需要实测时,用各自的压测工具、自己的消息大小和副本配置:

bash
# Kafka 3.9/4.0
bin/kafka-producer-perf-test.sh --topic bench --num-records 1000000 \
  --record-size 1024 --throughput -1 --producer-props \
  bootstrap.servers=broker:9092 acks=all

# RocketMQ 发行包自带 example(类路径以版本为准)
sh bin/tools.sh org.apache.rocketmq.example.benchmark.Producer namesrv:9876

判断依据:

  • Topic/Partition 总数超过单集群的舒适区,优先 RocketMQ。
  • 单 Topic 需要极高吞吐、下游是流计算生态,优先 Kafka。
  • 需要延迟、事务、Tag 过滤、DLQ 且不想自建,优先 RocketMQ 5.x。
  • 团队已有成熟 Kafka 平台和监控,迁移成本要计入选型。

生产动作 ​

  • 按「消息形态」而不是「公司用什么」选型。业务消息和日志管道可以用两套集群,没必要强行统一。
  • 把 Topic/Partition 数量作为一级容量指标。Kafka 扩 Partition 容易,但元数据、选举、恢复时间都会变差;RocketMQ 建 Topic 容易,但 Queue 文件、PageCache 和文件句柄仍要算。
  • 压测必须带副本和刷盘配置。单副本、异步刷盘的吞吐数字不能用于生产容量规划。
  • 迁移用双写/双读过渡,不要一次性切。双写要有幂等和对账;切换前用时间位点对齐消费进度。
  • 明确版本边界:Kafka 4.0 没有 ZooKeeper 模式;RocketMQ 5.x 的 Timer、Proxy、Controller、LiteTopic 在 4.9 都不存在。

边界 ​

  • 没有通用赢家。日志/流计算选 Kafka 更顺,业务消息/多 Topic/延迟事务选 RocketMQ 更省事,这是经验判断,不是定律。
  • 「Kafka 只能做日志」已经过时。Kafka 有事务、 compaction、KRaft,也能做业务消息;只是延迟、过滤、DLQ 需要自建。
  • 「RocketMQ 万级 Topic 无压力」要加限定。它不受「每 Topic 一套日志」的限制,但仍受 Queue 文件数、PageCache、文件句柄和 NameServer 路由大小的约束。
  • 不要把单个项目的选型表当成通用结论。项目里的选择受团队栈、历史包袱、云产品配额影响,换一个组织未必成立。
  • 不要用 4.x 的印象评价 5.x。5.x 的 Controller、Proxy、Timer、LiteTopic 改变了高可用、接入和延迟能力的边界。

讲清楚 ​

Kafka 和 RocketMQ 都是分区日志加副本,真正的差别在存储单元。Kafka 一个 Partition 一套日志文件,Partition 既是并行单位也是副本单位;RocketMQ 所有 Topic 共用一份 CommitLog,每个 Queue 只有一份 20 字节的索引。前者适合 Topic 少、单 Topic 流量大的场景,后者适合 Topic 多、每个 Topic 流量不大的业务消息。

副本和选主也不一样。Kafka 用 ISR,Leader 等 ISR 全员确认,配好 acks=all、min.insync.replicas 和不选脏主,已提交消息不会丢;它不是「最终一致」。RocketMQ 走过了经典主从、DLedger、Controller 三代,4.5 之后就能自动选主,5.x 的 Controller 把选主独立出来。

能力上要按版本说:Kafka 4.0 只支持 KRaft,没有原生延迟 Topic;RocketMQ 4.x 是 18 级延迟,5.x 用 Timer 支持任意时间点,还有 Proxy、Pop、LiteTopic。选型的顺序是:先数 Topic 和 Partition,再看单 Topic 吞吐,再看延迟/事务/过滤/死信是不是硬需求,最后算团队运维成本。只报「哪个性能高」说明不了问题。

把一门技术讲透到既懂也会用