消息队列 (MQ) 深度剖析:Kafka 与 RocketMQ (2026 版)
写在前面:
消息队列是分布式系统的血管,负责解耦、削峰和异步处理。在 2026 年,Kafka 和 RocketMQ 依然是市场的主流。面试官希望你不仅会用,还能通过源码级别理解它们的高吞吐原理、零拷贝技术、以及如何保证消息的可靠性与顺序性。
📨 第一部分:Kafka 高性能揭秘
1. 为什么 Kafka 吞吐量这么高?
高频问法:
- “Kafka 如何做到百万级 TPS?”
- “零拷贝 (Zero Copy) 是什么?”
深度解析:
- 顺序写磁盘 (Sequential Write):
- Kafka 将消息追加到日志文件末尾。机械硬盘的顺序写速度堪比内存随机写。
- 零拷贝 (Zero Copy):
- 传统 I/O:磁盘 -> 内核 Buffer -> 用户 Buffer -> 内核 Socket Buffer -> 网卡。4 次拷贝,4 次上下文切换。
- sendfile (Linux):磁盘 -> 内核 Buffer -> (描述符) -> 网卡。数据直接在内核态传输,0 次 CPU 拷贝。
- Page Cache:
- 大量利用操作系统的页缓存,而不是 JVM 堆内存。避免 GC 开销。
- 批量发送与压缩:
- Producer 将多条消息打包压缩(GZIP/Snappy/LZ4)后发送。
2. Kafka 架构设计
- Broker:服务节点。
- Topic:逻辑分类。
- Partition (分区):物理上的并发单元。一个 Topic 分为多个 Partition,分布在不同 Broker 上。Partition 是 Kafka 并发读写的基础。
- Consumer Group (消费者组):
- 组内单播:一条消息只能被组内一个消费者消费。
- 组间广播:不同组可以消费同一条消息。
🚀 第二部分:RocketMQ 核心场景
1. 事务消息 (Transaction Message)
场景:用户下单,扣减库存,并投递消息给积分系统。如何保证“本地事务”和“发送消息”的原子性?
RocketMQ 解决方案 (2PC 思想):
- 发送半消息 (Half Message):Producer 发送消息到 MQ,MQ 持久化成功但标记为“不可投递”。
- 执行本地事务:Producer 执行本地逻辑(如写数据库)。
- 提交/回滚:
- 本地事务成功 -> 发送 Commit -> MQ 将消息改为“可投递”。
- 本地事务失败 -> 发送 Rollback -> MQ 删除半消息。
- 回查机制 (Compensation):
- 如果第 3 步丢失,MQ 会定时反查 Producer 的事务状态。
2. 延时消息 (Delay Message)
场景:订单 30 分钟未支付自动关闭。
原理:
- RocketMQ 早期支持固定 Level (1s, 5s, ..., 30m)。RocketMQ 5.0+ 支持任意时间精度。
- 实现:消息先暂存在
SCHEDULE_TOPIC_XXXX队列中,到期后,Broker 将其还原到真实 Topic 中。
🛡️ 第三部分:通用难题与解决方案
1. 如何保证消息不丢失?(可靠性)
全链路保障:
- 生产端:
- Kafka:
acks=all(所有 ISR 副本确认)。 - RocketMQ: 同步发送 (
SYNC)。
- Kafka:
- 服务端 (Broker):
- 多副本机制 (Replication)。
- 刷盘策略:同步刷盘 (Sync Flush) 最安全但慢,异步刷盘 (Async Flush) 快但有风险。
- 消费端:
- 手动 Ack:业务逻辑执行成功后,再提交 Offset。绝对不能自动 Ack。
2. 如何保证消息顺序?
原理:MQ 通常只保证局部顺序(Partition/Queue 维度),不保证全局顺序。
方案:
- Producer:将需要顺序的消息(如同一个 OrderID 的创建、支付、发货),通过 Hash 算法发送到同一个 Partition/Queue。
- Consumer:确保同一个 Partition 只能被一个线程处理(或者使用内存队列进行局部串行化)。
3. 消息积压怎么办?
场景:消费者挂了,或者消费速度太慢,导致几百万条消息堆积。
紧急处理流程:
- 扩容:增加 Consumer 实例。
- 拆分:如果 Topic 的 Partition 不够,扩容 Consumer 也没用。
- 编写一个临时 Consumer,不处理业务,只把消息快速转发到一个新的 Topic(拥有 10 倍 Partition)。
- 启动 10 倍数量的 Worker Consumer 消费新 Topic。
- 排查:定位消费慢的原因(是死锁?是 DB 慢?还是 CPU 高?)。
总结:Kafka 胜在吞吐量,适合日志收集、大数据流计算;RocketMQ 胜在业务特性丰富(事务、延时、Tag 过滤),适合电商、金融业务。面试时需根据场景选型。
