NiceOffer

八股文解析

Kafka 和 RocketMQ 怎么选?

KafkaRocketMQMQ八股文

一句话结论

高吞吐、生态强选 Kafka;低延迟、强一致、事务要求高选 RocketMQ。

面试标准答法

1. 定位与核心差异

两者都是分布式消息中间件,但设计哲学不同:

  • Kafka:起源于 LinkedIn 日志聚合场景,核心是分布式提交日志(Distributed Commit Log),追求极致的顺序读写吞吐,牺牲部分功能(如不支持延迟消息、事务较弱)。
  • RocketMQ:起源于阿里电商业务,核心是队列模型 + 丰富消息语义,在吞吐接近 Kafka 的同时,补齐了延迟消息、事务消息、消息轨迹等业务刚需。

2. 存储模型对比(最关键的分水岭)

维度KafkaRocketMQ
存储粒度Partition(分区)Queue(队列)
顺序写每个 Partition 追加写,单 Partition 内有序每个 Queue 追加写,单 Queue 内有序
消费进度Offset(长整型)ConsumerOffset(长整型)
刷盘策略默认异步刷盘,可配置同步刷盘默认异步刷盘,可配置同步刷盘
文件结构每个 Partition 一个目录,segment 文件 + indexCommitLog 全局单一文件 + ConsumeQueue 逻辑队列

关键机制细节:

  • Kafka 的 Partition 是物理文件目录,Partition 数量直接决定文件句柄数,过多会打爆 OS 文件句柄(ulimit -n)。
  • RocketMQ 的 CommitLog 是单一物理文件(默认 1GB 滚动),ConsumeQueue 是逻辑索引,所以 RocketMQ 队列数可以开得很大(万级),而 Kafka 分区数建议控制在千级以内。
  • Kafka 的消费顺序保证是分区内有序,跨分区无序;RocketMQ 同理,队列内有序。两者都支持全局有序(Kafka 单分区 / RocketMQ 单队列),但都会牺牲并行度。

3. 功能特性对比

功能KafkaRocketMQ
延迟消息❌ 不支持(需自研或第三方)✅ 支持,18 个延迟级别(1s~2h)
事务消息✅ 2PC + 幂等(0.11+ 支持)✅ 2PC + 事务反查(更成熟)
消息轨迹❌ 需自研✅ 内置 trace 支持
死信队列✅ 0.11+ 支持(DLQ)✅ 支持(DLQ)
消息过滤❌ 仅按 key/header,需客户端过滤✅ 支持 Tag + SQL92 过滤
广播消费✅ 支持✅ 支持
消息重试✅ 手动 seek✅ 内置重试队列(16 次)
定时消息✅ 支持(1.2+ 版本)

4. 性能参数对比(同硬件压测参考值)

指标KafkaRocketMQ
单机吞吐(生产)100万+ msg/s70万+ msg/s
单机吞吐(消费)100万+ msg/s60万+ msg/s
端到端延迟(P99)10-50ms5-20ms
水平扩展分区级扩展,重分区成本高队列级扩展,扩容简单

5. 选型决策树

业务场景 → 需要延迟消息/事务消息/消息轨迹? 
    ├─ 是 → RocketMQ
    └─ 否 → 再看数据量级
        ├─ 日均亿级+,追求极致吞吐 → Kafka
        └─ 日均千万级,但要求低延迟 → RocketMQ

常见追问

追问要点
Kafka 为什么吞吐比 RocketMQ 高?① 零拷贝(sendfile 系统调用,减少 4 次上下文切换);② 批量发送(batch.size + linger.ms);③ 分区并行写(每个 Partition 独立顺序写);④ 消费端 pull 模式配合 long-polling。RocketMQ 也用了零拷贝和批量,但 CommitLog 单文件写存在锁竞争(虽然用了 mmap + 自旋锁优化)。
RocketMQ 事务消息是怎么实现的?① 发送 half message(半消息,对消费者不可见);② 执行本地事务;③ 提交/回滚 commit 消息;④ 若长时间未提交,Broker 回查(check back)生产者事务状态。核心是 2PC + 事务反查,反查机制保证最终一致性。Kafka 的事务是幂等生产者 + 事务协调器(Transaction Coordinator),但 Kafka 事务主要用于 EOS(Exactly-Once Semantics),不是业务事务。
RocketMQ 延迟消息为什么只有 18 个级别?延迟消息实现方式:消息写入后先进入 ScheduleLog(延迟队列),由定时线程扫描,到期后写入目标 Topic。18 个级别是预定义的延迟时间档位(1s/5s/10s/30s/1m...),不能自定义任意延迟时间,因为 Broker 内部用定时扫描 + 定时线程实现,任意延迟需要更复杂的时间轮(TimeWheel)设计。
Kafka 分区数怎么定?分区数 = max(生产吞吐 / 单分区吞吐, 消费吞吐 / 单消费者吞吐)。过多分区导致:① 文件句柄膨胀;② leader 选举耗时增加;③ 消费端 rebalance 变慢。经验值:分区数 ≤ Broker 数 × 4,单分区吞吐约 10-20MB/s。

面试回答模板(30 秒版)

延伸准备

  1. Kafka 的 KRaft(Kafka Raft Metadata)模式 —— 了解它如何替代 ZooKeeper 做元数据管理,以及 Raft 协议在元数据一致性中的应用。面试官问“Kafka 3.x 有什么变化”时能接住。
  2. RocketMQ 的 CommitLog 与 ConsumeQueue 映射原理 —— 能画出消息从生产到消费的完整链路:Producer → CommitLog(顺序写)→ ConsumeQueue(逻辑索引)→ Consumer 拉取。理解为什么 RocketMQ 队列数可以远大于 Kafka 分区数。
  3. 消息中间件的性能压测方法论 —— 能说出 benchmark 的维度:TPS、QPS、P99/P999 延迟、消息大小(128B/1KB/4KB)、ACK 策略(0/1/all)、批量大小对吞吐的影响。面试官问“你怎么验证你的选型结论”时,能给出可落地的方案。

想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。