八股文解析
Kafka 和 RocketMQ 怎么选?
一句话结论
高吞吐、生态强选 Kafka;低延迟、强一致、事务要求高选 RocketMQ。
面试标准答法
1. 定位与核心差异
两者都是分布式消息中间件,但设计哲学不同:
- Kafka:起源于 LinkedIn 日志聚合场景,核心是分布式提交日志(Distributed Commit Log),追求极致的顺序读写吞吐,牺牲部分功能(如不支持延迟消息、事务较弱)。
- RocketMQ:起源于阿里电商业务,核心是队列模型 + 丰富消息语义,在吞吐接近 Kafka 的同时,补齐了延迟消息、事务消息、消息轨迹等业务刚需。
2. 存储模型对比(最关键的分水岭)
| 维度 | Kafka | RocketMQ |
|---|---|---|
| 存储粒度 | Partition(分区) | Queue(队列) |
| 顺序写 | 每个 Partition 追加写,单 Partition 内有序 | 每个 Queue 追加写,单 Queue 内有序 |
| 消费进度 | Offset(长整型) | ConsumerOffset(长整型) |
| 刷盘策略 | 默认异步刷盘,可配置同步刷盘 | 默认异步刷盘,可配置同步刷盘 |
| 文件结构 | 每个 Partition 一个目录,segment 文件 + index | CommitLog 全局单一文件 + ConsumeQueue 逻辑队列 |
关键机制细节:
- Kafka 的 Partition 是物理文件目录,Partition 数量直接决定文件句柄数,过多会打爆 OS 文件句柄(
ulimit -n)。 - RocketMQ 的 CommitLog 是单一物理文件(默认 1GB 滚动),ConsumeQueue 是逻辑索引,所以 RocketMQ 队列数可以开得很大(万级),而 Kafka 分区数建议控制在千级以内。
- Kafka 的消费顺序保证是分区内有序,跨分区无序;RocketMQ 同理,队列内有序。两者都支持全局有序(Kafka 单分区 / RocketMQ 单队列),但都会牺牲并行度。
3. 功能特性对比
| 功能 | Kafka | RocketMQ |
|---|---|---|
| 延迟消息 | ❌ 不支持(需自研或第三方) | ✅ 支持,18 个延迟级别(1s~2h) |
| 事务消息 | ✅ 2PC + 幂等(0.11+ 支持) | ✅ 2PC + 事务反查(更成熟) |
| 消息轨迹 | ❌ 需自研 | ✅ 内置 trace 支持 |
| 死信队列 | ✅ 0.11+ 支持(DLQ) | ✅ 支持(DLQ) |
| 消息过滤 | ❌ 仅按 key/header,需客户端过滤 | ✅ 支持 Tag + SQL92 过滤 |
| 广播消费 | ✅ 支持 | ✅ 支持 |
| 消息重试 | ✅ 手动 seek | ✅ 内置重试队列(16 次) |
| 定时消息 | ❌ | ✅ 支持(1.2+ 版本) |
4. 性能参数对比(同硬件压测参考值)
| 指标 | Kafka | RocketMQ |
|---|---|---|
| 单机吞吐(生产) | 100万+ msg/s | 70万+ msg/s |
| 单机吞吐(消费) | 100万+ msg/s | 60万+ msg/s |
| 端到端延迟(P99) | 10-50ms | 5-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 秒版)
延伸准备
- Kafka 的 KRaft(Kafka Raft Metadata)模式 —— 了解它如何替代 ZooKeeper 做元数据管理,以及 Raft 协议在元数据一致性中的应用。面试官问“Kafka 3.x 有什么变化”时能接住。
- RocketMQ 的 CommitLog 与 ConsumeQueue 映射原理 —— 能画出消息从生产到消费的完整链路:Producer → CommitLog(顺序写)→ ConsumeQueue(逻辑索引)→ Consumer 拉取。理解为什么 RocketMQ 队列数可以远大于 Kafka 分区数。
- 消息中间件的性能压测方法论 —— 能说出 benchmark 的维度:TPS、QPS、P99/P999 延迟、消息大小(128B/1KB/4KB)、ACK 策略(0/1/all)、批量大小对吞吐的影响。面试官问“你怎么验证你的选型结论”时,能给出可落地的方案。
想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。