Kafka vs RabbitMQ
日志型 vs 传统 MQ 选型。
Kafka vs RabbitMQ
这一课你将能做到
- 用「日志型 vs 队列型」两句话区分 Kafka 与 RabbitMQ 的心智模型,并说清各自的数据保留方式差异
- 为埋点审计、任务队列、缓存失效、订单多下游四类场景选出更合适的组件(含 Redis),并各写一句理由
- 说明为什么主站仍是 MySQL + REST + 可选 Redis,Kafka 放在扩展实验位置
为什么要学
路线图上 Kafka、RabbitMQ、Redis 经常挤在一起,面试必问「怎么选」。选错的代价不是语法不通,而是:运维模型、回溯能力、路由灵活度和业务形状对不上——比如把「任务队列」架在 Kafka 上,然后为死信、延迟重试、单条重投把基础能力一个个手搓出来。
本课不评「谁更先进」,只做「形状匹配」:先建立两种模型的心智图,再给一棵可背下来的决策树。
人话:Kafka 像行车记录仪(先录下来,谁爱读谁读、读几遍都行);RabbitMQ 像工单窗口(任务领走办完就销单);Redis Pub/Sub 像扩音器(当时不在场就听不到)。
先建立图像
Kafka(日志型)
Topic/Partition 追加 → 多 Consumer Group 各持 offset 读 → 保留一段时间可重放
「先录下来;读不删,谁要谁读」
RabbitMQ(队列 / AMQP 型)
Exchange 路由 → Queue → Consumer ack 后消息删除(典型路径)
「任务进篮子,工人领走办完销单」
Redis Pub/Sub
发布瞬间广播 → 无历史
「正在听的人能收到,没在线就错过」
| 维度 | Kafka | RabbitMQ |
|---|
| 存储 | 分区日志,按时间/大小保留 | 队列,消费确认后常删除 |
| 消费模型 | 拉取 + 组内分摊 + offset | 推/拉结合,多种 ack |
| 吞吐 | 极高(顺序追加 + 零拷贝) | 中高 |
| 顺序 | 分区内有序 | 单队列内较直观 |
| 回溯重放 | 天然按 offset | 一般不是设计目标 |
| 路由 | Topic + 分区键为主 | Exchange 灵活(direct/topic/fanout/headers) |
| 延迟队列/死信 | 需自建或扩展 | 原生 TTL + DLX 开箱即用 |
| 协议与生态 | Kafka 协议、Streams/Connect | AMQP、STOMP/MQTT 插件 |
跟着做
步骤 1:用一句话翻译两种模型
合上对照表默写:
- Kafka:________________(答案方向:可重放的分布式日志,读不删)
- RabbitMQ:________________(答案方向:消费确认即删除的任务队列)
写完对照上文「记录仪 / 工单窗口」纠正。再打开 Kafka Use Cases 扫一遍标题,确认「事件流 / 数据管道」叙事。
步骤 2:场景卡片分类
对下列场景写「Kafka / RabbitMQ / Redis / 只 MySQL」+ 一句理由:
- 用户行为埋点、审计日志,需事后重放修数据
- 订单事件:通知、BI、搜索多订阅者
- 生成 PDF、调第三方 API、需要延迟重试与死信的任务队列
- 按 header 复杂路由到不同工人
- 课程详情缓存失效广播
- 改用户昵称写权威表
参考方向:1–2 Kafka(要重放/多订阅者);3–4 RabbitMQ(任务、路由、死信);5 Redis(瞬时广播);6 只 MySQL(单一真相源)。
步骤 3:对比 fanout 与多 Consumer Group
RabbitMQ fanout:一条进交换机 → 复制到多个队列 → 各工人消费自己的队列
Kafka:一条进 Topic → group notify 与 group audit 各持 offset → 各读一遍日志
写相似点(都支持一对多多订阅)与不同点(保留策略、重放能力、组内是否分摊、运维模型)。
步骤 4:做一道选型题
题:「管理端批量导入 1 万条课时」——偏 Kafka 还是 RabbitMQ?
写两条理由。提示:若核心是任务切片、失败重试、进度反馈,队列型更贴;若是导入完成后多下游投影/审计重放,事件日志更贴。混合形态也合法:「导入任务走队列,完成后的领域事件走 Kafka」——组件可以并存,边界要写清楚。
步骤 5:钉死本站立场
主站路径:Nginx → Spring Boot API → MySQL(权威)+ Redis(缓存/会话)。写进笔记:不上任何 MQ 也能完成主站;Kafka 是事件驱动能力扩展,先在实验环境把能力建起来,真实需求出现(多下游、重放、削峰)再接入。
步骤 6:写一段「给同事的选型备忘」
不超过 5 行:何时 Kafka、何时 RabbitMQ、何时 Redis、何时别上 MQ。用自己的话写,禁止空话「按业务选型」。写完贴进项目 README 或团队 Wiki——选型结论不落文字,三个月后一定重吵一遍。
讲清楚要点
- 因为Kafka 保留日志且读不删,所以擅长事件流、多订阅者、重放修数;不擅长当「复杂路由任务中心」的第一选择(死信、延迟、单条重投都要自建)。
- 因为RabbitMQ 的 Exchange/Queue/ACK/DLX 生态成熟,所以任务队列、延迟重试、灵活路由场景更顺手;但吞吐与回溯能力不是它的主战场。
- 因为Redis Pub/Sub 无历史,所以只适合瞬时通知(缓存失效、弹幕类);拿它当订单总线是事故预定。
- 因为每个 MQ 都是真实的运维负担(监控、容量、故障演练),所以小团队同步 REST + 事务往往更简单——MQ 不是架构荣誉勋章。
- 因为「高吞吐事件管道」与「每个任务精确投递工人」是两种形状,所以先问「要不要重放」「失败谁重试」「吞吐量级」,再谈组件品牌。
- 因为权威数据在 MySQL,所以无论选哪个 MQ,消息都只是事件/任务载体,不能替代事务库——这条在所有选型里不变。
你可能会懵的地方
-
「Kafka 也能当任务队列吗?」
技术上能(消息被组内消费),但死信、延迟队列、单条重试、优先级都要自己堆;RabbitMQ 开箱即用。如果团队已在用 RabbitMQ 且业务是任务型,不必为「流行」迁移。
-
「有了 Kafka 还要 Redis 吗?」
职责不同:Redis 管缓存/会话/计数这类热数据;Kafka 管事件流。一个站两者并存非常正常,互不替代。
-
「fanout 就是 Consumer Group 吗?」
相似在「一对多」:fanout 复制到多个队列,Kafka 多组各读一份。不同在:fanout 的各队列独立删除消息,Kafka 是同一份日志多个 offset;Kafka 组内还有分摊语义。
-
「Kafka 分区内有序,能不能替代单队列顺序任务?」
顺序绑定在分区键上,跨 key 仍并行。若业务是「全局只有一个工人按序执行」,经典单队列更直观;用 Kafka 就要接受「按实体有序、全局无序」,或硬压成单分区(吞吐锁死)。
-
「必须二选一吗?」
不必。并存很常见:任务走 RabbitMQ、领域事件走 Kafka。但每多一个中间件就多一套监控与故障面,理由要写进 ADR,而不是「都想要」。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 用 Redis Pub/Sub 当订单事件总线 | 无历史、无分摊,事故无法重放 | 订单多下游 → Kafka(或专业 MQ) |
| 学习型站点强行上 Kafka 才算「架构完整」 | 运维成本远超收益 | 主栈 MySQL/REST;MQ 作扩展实验 |
| 只因「Kafka 更火」替换已有 RabbitMQ 任务系统 | 迁移成本高,能力错配 | 按回溯/吞吐/路由需求评估,不按品牌 |
| 缓存失效也发 Kafka 再通知删 key | 过重,链路多一跳多一故障点 | 缓存失效 → Redis Pub/Sub/轻广播 |
| 审计要重放一年却放 RabbitMQ 队列 | 消费即删,重放无门 | 审计事件进 Kafka 按时间保留 |
卡点急救
- 选型争论不收敛:把问题变成三个问题——要不要重放?失败后谁重试、要不要死信?量级多大?答案指到决策树上,比比谁用得多有效。
- 已经用错组件要迁:先加并行通道(新事件同时双写旧与新),下游逐步切换消费,观测 lag 与错误率,最后摘旧——迁移期内两套都要监控。
- 面试被「你们为什么用 X」问住:答需求形状 + 已知代价 + 简单性原则三段式,配合一个真实场景(如订单多下游)展开,比背参数表可信。
面试常问
-
Kafka 和 RabbitMQ 的本质区别?
心智模型:Kafka 是分布式提交日志——消息追加保留、消费读 offset、读不删,天然支持重放与多订阅,吞吐靠顺序写与批量极高;RabbitMQ 是AMQP 消息代理——Exchange 路由到 Queue,消费者 ack 后消息删除,路由灵活、延迟/死信原生支持,适合任务分发。选型按形状:事件流/管道/重放 → Kafka;任务/路由/死信 → RabbitMQ。
-
什么场景下你们会不用 MQ?
①链路里没有真正的异步需求(用户必须等结果,如支付回调校验);②流量小到同步调用毫无压力(QPS 个位数到百级);③没有运维 MQ 的人力(监控、容量、故障演练)。此时同步 REST + 数据库事务最简单可靠——架构简单性也是架构能力。
-
为什么 Kafka 吞吐比 RabbitMQ 高?
①顺序写磁盘(追加日志,顺序 IO 远快于随机 IO);②PageCache(读写走 OS 缓存,不依赖 JVM 堆 GC);③零拷贝 sendfile(数据不过用户态);④批量+压缩传输;⑤消费端拉取模型,服务端不维护复杂推送状态。RabbitMQ 的单条确认、灵活路由、消息状态管理都是为「可靠任务投递」付出的开销。
自测三问
- 批量导入 1 万条课时:你选谁?写出两条理由。
- RabbitMQ fanout 与 Kafka 多 Consumer Group:相似点、不同点各一条。
- 只需缓存失效广播时,第三选项是什么?为什么不优先 Kafka?
小结一句话
Kafka 擅长大管道事件流与重放,RabbitMQ 擅长任务与灵活路由,Redis 管缓存与轻通知——按问题形状选,不按热度选;权威数据永远在 MySQL。
延伸