1. 介绍一下 RocketMQ 的核心组件和工作原理
💡 知识点解析:
RocketMQ 的核心角色主要是 Producer、Consumer、Broker、NameServer。Producer 负责发消息,Consumer 负责消费消息,Broker 负责存储和转发消息,NameServer 负责路由注册与发现。官方文档明确说明,Producer/Consumer 会先从 NameServer 获取路由信息,再直接和 Broker 建立连接进行收发消息。
🗣️ 面试参考回答:
"RocketMQ 是一个分布式消息中间件,核心组件主要有四个:Producer、Consumer、Broker 和 NameServer。
Producer 负责发送消息,Consumer 负责订阅和处理消息,Broker 负责消息存储、投递和重试等核心功能,NameServer 则负责维护 Topic 和 Broker 的路由信息。
它的基本工作流程是:
-
Broker 启动后向 NameServer 注册;
-
Producer 发送消息前,先去 NameServer 拉取 Topic 的路由信息;
-
Producer 根据路由选择一个 MessageQueue 所在的 Broker 发送消息;
-
Consumer 也会从 NameServer 获取路由,然后直接从 Broker 拉取消息进行消费。
所以 RocketMQ 的设计里,NameServer 更像轻量级路由中心,Broker 才是真正承载消息存储和投递的核心节点。"
🎯 面试追问:
为什么 RocketMQ 不用 ZooKeeper 做注册中心?
2. RocketMQ 中 Topic、MessageQueue、ConsumerGroup 分别是什么?
💡 知识点解析:
RocketMQ 的基本消息模型是 Pub/Sub。Topic 是逻辑分类,MessageQueue 是 Topic 下的物理队列分片,ConsumerGroup 是一组消费行为一致的消费者,用于负载均衡和消费进度管理。官方文档也提到 RocketMQ 会基于每个 ConsumerGroup 记录消费进度。
🗣️ 面试参考回答:
"在 RocketMQ 里,Topic 是消息的逻辑分类 ,比如订单消息、支付消息都可以放不同 Topic。
但是 Topic 下面通常不会只有一个队列,而是会拆成多个 MessageQueue,这样可以提高并发能力和吞吐量。
而 ConsumerGroup 是一个消费组,组内多个消费者共同消费同一个 Topic 的消息,RocketMQ 会做负载均衡,把不同队列或者消息分配给组内不同消费者处理。
另外,RocketMQ 不是简单地删掉已消费消息,而是会基于 ConsumerGroup 维护消费位点,也就是 offset,用来记录消费进度。"
🎯 面试追问:
一个 Topic 为什么要拆多个队列?
3. RocketMQ 有哪些消息发送方式?
💡 知识点解析:
官方文档明确提到 Producer 支持 synchronous、asynchronous、one-way、ordered 等发送方式。
🗣️ 面试参考回答:
"RocketMQ 常见发送方式主要有四种:
-
同步发送:发送方等 Broker 返回结果后再继续执行,适合重要业务消息;
-
异步发送:发送后不阻塞当前线程,通过回调拿结果,适合提高吞吐;
-
单向发送:只发不等确认,性能最好,但可靠性最弱,适合日志类场景;
-
顺序发送:把同一业务标识的消息发到同一个队列,保证局部有序。
如果是下单、支付这类关键链路,一般优先同步发送;如果是埋点、日志这类对实时确认要求不高的场景,可以用异步或者单向发送。"
🎯 面试追问:
你项目里下单消息为什么不用单向发送?
4. RocketMQ 的消费模式有哪些?
💡 知识点解析:
官方文档说明 Consumer 支持 push / pull 两类消费方式,也支持 cluster / broadcast 两类消费模型。重试特性在广播模式下并不生效。
🗣️ 面试参考回答:
"RocketMQ 从消费接口上看,有 Push 和 Pull 两类;从消费语义上看,常见的是 集群消费 和 广播消费。
-
集群消费:同一个消费组里的消费者分摊消息,适合订单、库存这类只能被一个实例处理一次的业务;
-
广播消费:每个消费者都会收到同一份消息,适合配置同步、缓存刷新这类场景。
实际项目里最常用的是集群消费,因为它能天然支持横向扩容。
另外要注意,RocketMQ 的重试机制主要是针对集群消费,广播模式下失败后不会按常规方式重试。"
🎯 面试追问:
你的票务系统为什么选择集群消费?
5. RocketMQ 如何保证消息不丢?
💡 知识点解析:
这个问题通常分成三段回答:生产端、Broker 端、消费端。官方文档里虽然分散在不同页面,但明确提到了发送确认、消费 ACK/重试、以及 Broker 存储与重投递机制。
🗣️ 面试参考回答:
"RocketMQ 保证消息可靠性,我一般会从三层说:
第一,生产端。
发送关键消息时用同步发送,拿到 Broker 的发送结果后再返回业务成功;发送失败要有重试、落库或者告警。
第二,Broker 端。
Broker 负责消息存储和投递,是可靠性的核心。生产者拿到成功响应,说明消息已经被 Broker 正常接收。
第三,消费端。
消费成功后才确认;如果消费失败,RocketMQ 会进入重试流程,超过最大重试次数后进入死信队列。
所以整体是:发送成功确认 + Broker 持久化存储 + 消费失败重试/DLQ,三层一起保障消息不丢。"
🎯 面试追问:
如果消费者业务执行成功了,但回执丢了,会发生什么?
6. RocketMQ 为什么会重复消费?怎么保证幂等?
💡 知识点解析:
RocketMQ 的消费语义更适合理解成 至少一次。只要出现网络抖动、消费超时、ACK 异常,就可能触发重复投递,所以幂等必须业务侧保证。官方文档对重试和 DLQ 机制有清晰说明。
🗣️ 面试参考回答:
"RocketMQ 在工程上要按 至少一次投递 去理解,所以重复消费是正常现象,不是 bug。
比如消费者业务已经执行成功了,但结果回传失败,Broker 可能认为这条消息没成功消费,于是再次投递。
解决方案不是指望 MQ 完全不重,而是 消费者要做幂等。常见做法有:
-
给消息设置业务唯一键,比如订单号、流水号;
-
消费前先查 Redis 或数据库判断是否处理过;
-
数据库层加唯一索引或状态机推进,防止重复插入和重复更新。
我项目里如果是订单创建、出票记录落库这种场景,通常会配合 唯一键 + 状态机 做幂等,这样即使 RocketMQ 重投,也不会造成重复下单或重复出票。"
🎯 面试追问:
如果 Redis 判重成功后,业务执行失败怎么办?
7. RocketMQ 的顺序消息是怎么实现的?
💡 知识点解析:
官方文档强调:要想保证 FIFO,需要同时保证 生产顺序 和 消费顺序,并且相同消息组要进入同一个队列;消费端更推荐串行消费,否则可能乱序。
🗣️ 面试参考回答:
"RocketMQ 的顺序消息不是全局有序,而是 局部有序 。
核心思路是:同一业务标识的消息必须发送到同一个队列,再由消费端按顺序串行处理。
比如订单创建、支付、取消,这三个消息如果要保证顺序,就可以按 orderId 做路由,把同一订单的消息固定投到同一个 MessageQueue。
消费端再使用顺序消费,避免并发打乱顺序。
所以顺序消息本质上是:
-
生产端按业务 key 选定固定队列;
-
消费端对该队列内消息按顺序处理。
它保证的是同一业务维度的有序,而不是整个 Topic 全局有序。"
🎯 面试追问:
为什么不建议追求全局有序?
8. RocketMQ 的延时消息有什么用?怎么实现?
💡 知识点解析:
官方文档给出的典型场景就是 订单超时取消。RocketMQ 5.x 延时消息本质是按指定时间投递;4.x 文档里常见的是基于延迟级别。
🗣️ 面试参考回答:
"延时消息就是消息发出去后,不会立刻投递给消费者,而是在指定时间后再投递。
典型场景就是:下单后 30 分钟未支付,自动取消订单。
RocketMQ 官方就把这种场景作为延时消息的典型用法。
在 RocketMQ 5.x 里,可以按时间戳指定投递时刻;在 4.x 里,常见做法是配置延迟级别。
相比自己扫数据库做超时任务,延时消息的优点是:
-
不需要频繁扫表;
-
分布式场景下更容易扩展;
-
触发逻辑和业务逻辑解耦。"
🎯 面试追问:
如果延时消息到了,但订单已经支付了,怎么处理?
9. RocketMQ 的事务消息是什么?适合什么场景?
💡 知识点解析:
官方文档明确给出事务消息的本质:保证消息发送和本地事务之间的最终一致性 。它的核心机制是 半消息(half message) + 本地事务执行 + 事务回查。
🗣️ 面试参考回答:
"RocketMQ 事务消息主要解决的是:本地事务成功了,但消息没发出去;或者消息发出去了,但本地事务失败了 这种不一致问题。
它的流程分两阶段:
-
先发一个 半消息 给 Broker,这时候消费者不可见;
-
生产者执行本地事务;
-
如果本地事务成功,就提交事务消息;失败就回滚;
-
如果 Broker 长时间没收到二次确认,就会发起 事务回查,让生产者确认这条消息到底该提交还是回滚。
它适合那种跨系统但又不想上强一致分布式事务的场景,比如 订单创建成功后,要通知下游积分、优惠券、短信系统 。
这种场景下,事务消息比直接依赖本地事务或者简单重试更稳。"
🎯 面试追问:
事务消息能不能代替 Seata?
10. RocketMQ 的重试机制和死信队列是怎样的?
💡 知识点解析:
官方文档明确说明:消费失败后,RocketMQ 会按重试策略再次投递;超过最大重试次数后,消息会进入 DLQ(死信队列)。对于 PushConsumer,非顺序消息的重试间隔是递增的。
🗣️ 面试参考回答:
"RocketMQ 里,消费者消费失败后,不会立刻把消息丢掉,而是会进入 重试机制 。
如果多次重试还是失败,超过最大重试次数后,就进入 死信队列 DLQ。
DLQ 可以理解成一个兜底隔离区,说明这条消息已经不适合继续正常重试了,需要人工排查或者专门补偿。
RocketMQ 官方文档里也提到,DLQ 通常是和具体 ConsumerGroup 对应的。
所以线上处理思路一般是:
-
短暂故障:靠自动重试恢复;
-
持续失败:进入死信队列;
-
运维或开发根据死信原因做补偿、修复或人工干预。"
🎯 面试追问:
消费异常时,是应该一直重试,还是尽快进死信?
11. RocketMQ 消息堆积了怎么办?
💡 知识点解析:
这个更多考察工程经验。虽然官方文档重点在消费负载均衡和重试,但思路通常是:先定位消费慢的原因,再扩消费能力,再做降级和补偿。RocketMQ 支持消费组扩容和负载均衡。
🗣️ 面试参考回答:
"消息堆积本质上是 生产速度超过消费速度 。
我一般会按三步排查:
-
先看消费者是不是挂了,或者业务逻辑变慢了,比如慢 SQL、锁竞争、远程调用阻塞;
-
再看能不能扩消费者实例,利用消费组负载均衡提高吞吐;
-
最后做临时止损,比如限流生产端、降级非核心业务、必要时补偿消费。
如果在面试里结合项目说,我会说:票务系统秒杀流量上来时,RocketMQ 主要做异步削峰,但前提是消费端必须稳。如果消费端写库或调用支付服务太慢,堆积一定会出现,所以不能只会用 MQ,还要会分析下游瓶颈。"
🎯 面试追问:
为什么加了 MQ 还是会把系统打挂?
12. RocketMQ 和 Kafka / RabbitMQ 的区别怎么答?
💡 知识点解析:
这题常考,但最忌讳泛泛而谈。对你这种 Java 后端实习面试,更推荐从 业务场景 去答,而不是背参数。你给的参考文章本身是 RabbitMQ 题库风格,我这里延续这个答法,但建议你在口头上强调"我项目里为什么选 RocketMQ"。
🗣️ 面试参考回答:
"如果从业务选型角度看:
-
RabbitMQ:路由能力强,模型灵活,适合业务编排复杂、吞吐要求没那么极致的场景;
-
Kafka:吞吐非常高,更偏日志、埋点、流式数据场景;
-
RocketMQ:在业务消息场景下比较均衡,既有不错的吞吐,也比较强调顺序消息、延时消息、事务消息这些业务特性。
所以如果是订单、支付、库存、票务这些偏业务事务链路,我会更倾向 RocketMQ;如果是日志采集、行为埋点、大数据管道,更容易想到 Kafka。