Skip to content

MQ选型对比-Kafka-RocketMQ-RabbitMQ ​

看在前面 ​

「Kafka、RocketMQ、RabbitMQ 怎么选?」是 MQ 板块的收官题。面试官不是要你背参数表,而是验证两件事。一是你有没有真实场景驱动的选型逻辑(而不是「我们公司用什么我说什么好」)。二是你知不知道每个 MQ 的设计取舍从哪来(吞吐和功能天然互斥)。

建议的答题姿势:先一句结论给场景,再给对比维度,最后落到自己项目的真实选择。前置阅读:Kafka架构与高性能原理、事务消息与延迟消息。

六维对比总表 ​

维度KafkaRocketMQRabbitMQ
吞吐量百万级/s(单机)十万级/s(单机)万级/s
延迟ms 级(攒批后几 ms~几十 ms)ms 级微秒级(最低)
功能特性流处理、事务(EOS)、紧凑日志事务消息、延迟消息、消息轨迹、重试/死信队列完善路由最强(exchange 四种模式)、优先级、TTL 灵活
顺序分区内有序(标准能力)队列有序 + 顺序消费监听器队列有序(单队列单消费者)
语言/模型Scala/Java,磁盘 log 结构,pullJava(可读可改),pull,存储引用 Java 生态Erlang,push 为主,AMQP 协议
运维复杂度中(KRaft 后变简单,但分区/存储调优深)中(NameServer 无状态,组件少)低(管理界面成熟,集群扩容需停部分流量)
适用场景日志采集、大数据管道、流计算、事件溯源交易业务、订单链路、金融对一致性要求高中小规模业务、复杂路由、多语言异构系统

三个数字级别的来源要能解释:Kafka 靠顺序写+零拷贝+批量(见 Kafka架构与高性能原理)。RabbitMQ 的 Erlang 进程模型换来了低延迟和海量连接,但消息落盘和复制设计让吞吐量级掉下来。

设计哲学:一个三角 impossible ​

text
                     ▲
                    ╱ ╲
                   ╱   ╲
                  ╱     ╲
                 ╱  取舍  ╲
                ╱         ╲
               ▲───────────▲
      功能丰富              低延迟
   (RocketMQ 加料)      (RabbitMQ 主场)
  • Kafka:为吞吐牺牲功能——没有延迟消息、没有完善的重试队列(客户端自己实现)、路由能力几乎为零。
  • RocketMQ:站在 Kafka 肩膀上(顺序写、pull 模型)做业务功能补全——事务消息、定时消息、死信、轨迹,吞吐让出一截。
  • RabbitMQ:AMQP 语义完备,路由与低延迟是王牌,吞吐天花板最低。 理解三角,选型就从「背表」变成「推导」。

各自经典适用案例 ​

Kafka:日志与数据管道 ​

  • 日志采集(ELK 前置 Kafka 削峰)、埋点上报、CDC 到数仓(Debezium → Kafka → 湖仓)、Flink/Spark 流计算 source、大促峰值写削峰。
  • 共性:海量、可回放、允许重复(下游幂等,或管道内 exactly-once)、对高级路由无需求。日志场景里 Kafka 的分区模型 + 长期存储(甚至拿 Kafka 当存储用,compact topic 做 KV 状态)就是最优解。

一个典型日志管道拓扑:

text
 App/网关(Nginx/埋点SDK)
     │ Filebeat/SDK 直投
     ▼
 Kafka(topic: app-log, 30 分区, 3 副本, 保留 3 天)
     │                        │
     ▼                        ▼
 Logstash 消费组           Flink 作业(实时大盘/告警)
     │                        │
     ▼                        ▼
 Elasticsearch/ClickHouse  实时指标库
 峰值 50w/s 的写入对 Kafka 是舒适区,对另外两家都是灾难

RocketMQ:交易与订单链路 ​

  • 下单后发券/积分/通知(事务消息保证 DB 与消息一致,见 事务消息与延迟消息)。订单超时取消(延迟消息)、削峰填谷 + 失败重试 + 死信告警的完整链路。
  • 阿里系/电商公司主力 MQ,Java 源码可读可改,出问题能深入排查。消息轨迹(谁发的、什么时候到哪个队列、谁消费的)对交易问题排查价值极大。
  • 部署形态:NameServer(无状态,不需要像 ZooKeeper 那样考虑元数据一致性)+ Broker 主从(Dledger 走 Raft 自动选主)。组件数比 ZK 时代的 Kafka 还少。

RabbitMQ:中小规模与异构路由 ​

  • 多语言系统解耦(AMQP 是跨语言标准协议)、复杂分发(fanout 给全量、topic 按模式匹配、headers 按属性)。任务分派(work queue + ack 机制天然负载均衡)、低延迟 RPC reply 队列。
  • 共性:量不大(万级/s 内)、路由逻辑复杂、团队运维能力有限。管理界面 + 插件生态让小团队也能稳稳用住。

路由能力是它不可替代的理由,四种 exchange 一图流:

text
                 ┌─ direct ──── routingKey 精确匹配 ──► Queue A (订单.*)
 Producer ──► Exchange ─ topic ──── routingKey 通配匹配 ──► Queue B (log.*)
   (AMQP)       ├─ fanout ──── 广播到所有绑定队列 ─────► Queue C / D
                └─ headers ── 按消息属性匹配(忽略 key)
 Kafka 里等价能力要靠「发送端分区 + 多 topic + 下游自筛」拼出来

选型之外的落地检查清单 ​

选定之后,落地前还要过四道坎,面试里主动提这些显得有实战:

  • 容量评估:峰值 QPS × 峰值时长 × 消息大小 → 分区数/队列数、磁盘保留期(Kafka 按字节或时间保留,超了直接删)。
  • 可靠性基线:三环节设防的参数直接抄作业——Kafka 见 消息不丢失与不重复。RocketMQ 同步刷盘 + 同步复制。RabbitMQ 队列/消息开持久化 + publisher confirm。
  • 可观测性:lag 告警(Kafka Exporter / Burrow)、RocketMQ Console、RabbitMQ 管理端;没有 lag 监控的 MQ 等于盲飞。
  • 降级预案:MQ 整体不可用时业务怎么办——本地消息表暂存、读旧库存量兜底,这是大促预案的必答题。

面试选型话术 ​

一段可以直接说的完整回答 ​

「我按三个问题选型:第一问量级——日志、埋点、大数据管道这种十万级以上吞吐、可回放的,选 Kafka,它的顺序写加零拷贝的存储模型就是这个场景的天花板,我们再用它喂 Flink 做实时数仓。第二问业务语义——交易链路要本地事务和消息一致、要延迟消息做订单超时、要重试死信的完整闭环,选 RocketMQ,这些它原生都有,Kafka 要自己在客户端拼。第三问路由与规模——中小流量、多语言团队、分发逻辑复杂,RabbitMQ 的 exchange 模型和管理界面最省心。如果是新项目且团队没有历史包袱,国内电商类业务我默认 RocketMQ,数据管道默认 Kafka,两者并存是常态而不是二选一。」

追问链 ​

Q1:你们为什么不能只用一个 Kafka?

Kafka 缺延迟消息、事务消息不覆盖外部 DB、重试/死信要客户端自建。交易链路用它等于自己造半个 RocketMQ。反过来把订单量塞给 RabbitMQ 又会在大促削峰时顶不住。双 MQ 并存(管道用 Kafka、业务用 RocketMQ)是业界常态,敢于说并存比硬选一个更真实。

Q2:Pulsar 了解吗?存算分离是干嘛的?

Pulsar 把 broker(无状态计算层)和 BookKeeper(存储层)拆开。扩容计算不搬数据、分层存储天然支持冷数据下沉,跨地域复制强。代价是组件多、运维面大、社区(国内)资料少。属于「知道趋势、能讲取舍」的加分项。

Q3:Kafka 为什么不适合做延迟消息?

log 结构按 offset 消费,没有「按时间到期」的索引。要支持就得像 RocketMQ 那样引入独立的调度 topic/时间轮。而 Kafka 的设计目标是吞吐管道,没有为调度语义付账。展开见 事务消息与延迟消息。

Q4:RabbitMQ 吞吐为什么上不去?

Erlang 进程和 Mnesia 元数据在大队列(百万级未消费消息)下性能塌陷。镜像队列是同步全量复制,扩副本即扩延迟。消息路由在 broker 端做(exchange 绑定匹配),海量消息时 CPU 消耗在分发上。Kafka 的路由在发送端就算好(分区器),broker 只管顺序写。

Q5:消息积压了怎么办?这和选型有关系吗?

紧急:扩消费者(不超过分区/队列数)、跳过非关键消费、临时新 topic 做分流管道。根治:容量评估 + 分区数预留 + 监控 lag 告警。和选型的关系:Kafka 扩分区不搬数据,积压扩容最从容。RocketMQ 扩队列同理。RabbitMQ 加消费者受队列数限制且大队列性能差——积压场景本身就体现了三种架构的伸缩模型差异。

Q6:怎么回答「为什么不用 Redis 的 pub/sub」?

Redis pub/sub 无持久化(断线丢消息)、无消费确认、无重试死信,它是「广播通知」不是「消息队列」。Stream 类型补了持久化但集群模式下单 stream 不能跨节点扩展,只适合轻量场景。

Q7:自研 MQ 值得吗?

不建议从零自研,但「封装」值得:公司级做一层统一 SDK(收发、轨迹、监控埋点、降级开关)。底下换 MQ 不动业务代码。真正自研的只有头部公司有规模收益(如美团的基于 Kafka 改造)。中小团队的成本是重构不动的。

面试官视角小结 ​

  • 六维表是骨架,但满分答案必须有三角取舍模型(吞吐-功能-延迟不可兼得)和每个 MQ 的设计根源。能推导的选型才可信。
  • 案例要具体到「事务消息用在下单发券」「延迟消息用在订单超时取消」这种粒度。建议带一个自己踩过的坑(如 RabbitMQ 大队列积压、Kafka rebalance 风暴)。
  • 「双 MQ 并存」是体现工程成熟度的关键句。知道没有银弹、知道并存成本(两套运维、两套客户端封装)的候选人,通常真的做过架构。
  • 主动提 Pulsar 存算分离、KRaft 去 zookeeper 化这类趋势,把话题引到自己熟悉的领域,这是面试的高级方法。
  • 与前几篇串起来就是完整的 MQ 知识体系。架构(Kafka架构与高性能原理)→ 可靠性(消息不丢失与不重复)。顺序(顺序消息)→ 事务与延迟(事务消息与延迟消息)→ 选型(本篇)。
  • 减分项:只说「Kafka 吞吐大」却说不出为什么大;把 RabbitMQ 说成「性能差所以没人用」;选型答案和自己项目场景对不上。

2026-10 新增(P0 补全)。