Skip to content

消息队列 (MQ) 深度剖析:Kafka 与 RocketMQ (2026 版)

写在前面

消息队列是分布式系统的血管,负责解耦、削峰和异步处理。在 2026 年,Kafka 和 RocketMQ 依然是市场的主流。面试官希望你不仅会用,还能通过源码级别理解它们的高吞吐原理、零拷贝技术、以及如何保证消息的可靠性与顺序性


📨 第一部分:Kafka 高性能揭秘

1. 为什么 Kafka 吞吐量这么高?

高频问法

  • “Kafka 如何做到百万级 TPS?”
  • “零拷贝 (Zero Copy) 是什么?”

深度解析

  1. 顺序写磁盘 (Sequential Write)
    • Kafka 将消息追加到日志文件末尾。机械硬盘的顺序写速度堪比内存随机写。
  2. 零拷贝 (Zero Copy)
    • 传统 I/O:磁盘 -> 内核 Buffer -> 用户 Buffer -> 内核 Socket Buffer -> 网卡。4 次拷贝,4 次上下文切换。
    • sendfile (Linux):磁盘 -> 内核 Buffer -> (描述符) -> 网卡。数据直接在内核态传输,0 次 CPU 拷贝
  3. Page Cache
    • 大量利用操作系统的页缓存,而不是 JVM 堆内存。避免 GC 开销。
  4. 批量发送与压缩
    • Producer 将多条消息打包压缩(GZIP/Snappy/LZ4)后发送。

2. Kafka 架构设计

  • Broker:服务节点。
  • Topic:逻辑分类。
  • Partition (分区):物理上的并发单元。一个 Topic 分为多个 Partition,分布在不同 Broker 上。Partition 是 Kafka 并发读写的基础
  • Consumer Group (消费者组)
    • 组内单播:一条消息只能被组内一个消费者消费。
    • 组间广播:不同组可以消费同一条消息。

🚀 第二部分:RocketMQ 核心场景

1. 事务消息 (Transaction Message)

场景:用户下单,扣减库存,并投递消息给积分系统。如何保证“本地事务”和“发送消息”的原子性?

RocketMQ 解决方案 (2PC 思想)

  1. 发送半消息 (Half Message):Producer 发送消息到 MQ,MQ 持久化成功但标记为“不可投递”。
  2. 执行本地事务:Producer 执行本地逻辑(如写数据库)。
  3. 提交/回滚
    • 本地事务成功 -> 发送 Commit -> MQ 将消息改为“可投递”。
    • 本地事务失败 -> 发送 Rollback -> MQ 删除半消息。
  4. 回查机制 (Compensation)
    • 如果第 3 步丢失,MQ 会定时反查 Producer 的事务状态。

2. 延时消息 (Delay Message)

场景:订单 30 分钟未支付自动关闭。

原理

  • RocketMQ 早期支持固定 Level (1s, 5s, ..., 30m)。RocketMQ 5.0+ 支持任意时间精度。
  • 实现:消息先暂存在 SCHEDULE_TOPIC_XXXX 队列中,到期后,Broker 将其还原到真实 Topic 中。

🛡️ 第三部分:通用难题与解决方案

1. 如何保证消息不丢失?(可靠性)

全链路保障

  1. 生产端
    • Kafka: acks=all (所有 ISR 副本确认)。
    • RocketMQ: 同步发送 (SYNC)。
  2. 服务端 (Broker)
    • 多副本机制 (Replication)。
    • 刷盘策略:同步刷盘 (Sync Flush) 最安全但慢,异步刷盘 (Async Flush) 快但有风险。
  3. 消费端
    • 手动 Ack:业务逻辑执行成功后,再提交 Offset。绝对不能自动 Ack。

2. 如何保证消息顺序?

原理:MQ 通常只保证局部顺序(Partition/Queue 维度),不保证全局顺序。

方案

  • Producer:将需要顺序的消息(如同一个 OrderID 的创建、支付、发货),通过 Hash 算法发送到同一个 Partition/Queue
  • Consumer:确保同一个 Partition 只能被一个线程处理(或者使用内存队列进行局部串行化)。

3. 消息积压怎么办?

场景:消费者挂了,或者消费速度太慢,导致几百万条消息堆积。

紧急处理流程

  1. 扩容:增加 Consumer 实例。
  2. 拆分:如果 Topic 的 Partition 不够,扩容 Consumer 也没用。
    • 编写一个临时 Consumer,不处理业务,只把消息快速转发到一个新的 Topic(拥有 10 倍 Partition)。
    • 启动 10 倍数量的 Worker Consumer 消费新 Topic。
  3. 排查:定位消费慢的原因(是死锁?是 DB 慢?还是 CPU 高?)。

总结:Kafka 胜在吞吐量,适合日志收集、大数据流计算;RocketMQ 胜在业务特性丰富(事务、延时、Tag 过滤),适合电商、金融业务。面试时需根据场景选型。

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情