RocketMQ 面试题精选
2026/1/14大约 7 分钟
RocketMQ 面试题精选
面试题分布
一、基础概念
1. 什么是消息队列?为什么要用消息队列?
消息队列是一种应用程序间的异步通信方式,生产者发送消息到队列,消费者从队列获取消息处理。
核心作用:
- 异步解耦:服务间不直接调用,降低耦合度
- 流量削峰:高峰期消息堆积,平稳消费
- 数据分发:一份数据分发给多个消费者
2. RocketMQ 有哪些核心组件?
| 组件 | 作用 |
|---|---|
| NameServer | 注册中心,管理 Broker 路由信息 |
| Broker | 消息存储服务器,负责消息存储和转发 |
| Producer | 消息生产者 |
| Consumer | 消息消费者 |
3. Topic、Tag、Queue 的区别?
| 概念 | 说明 | 类比 |
|---|---|---|
| Topic | 消息主题,一类消息的集合 | 一级分类 |
| Tag | 消息标签,同一 Topic 下的过滤 | 二级分类 |
| Queue | 消息队列,Topic 的物理分区 | 实际存储单元 |
二、架构原理
4. RocketMQ 的架构是怎样的?
5. NameServer 为什么不用 ZooKeeper?
| 对比项 | NameServer | ZooKeeper |
|---|---|---|
| 设计 | 无状态,节点独立 | 有状态,需要选举 |
| 一致性 | 最终一致性 | 强一致性(CP) |
| 复杂度 | 简单轻量 | 相对复杂 |
| 性能 | 更高 | 较低 |
结论:RocketMQ 对一致性要求不高,NameServer 更简单高效。
6. 消息存储结构是怎样的?
- CommitLog:所有消息顺序写入,保证写入性能
- ConsumeQueue:存储消息在 CommitLog 中的偏移量
- IndexFile:支持按 Key 或时间查询
7. 为什么 CommitLog 要顺序写?
顺序写 vs 随机写:
- 顺序写磁盘速度接近内存
- 随机写需要频繁寻道,性能差
RocketMQ 通过顺序写 CommitLog + 异步构建索引,实现高吞吐。
三、消息类型
8. RocketMQ 支持哪些消息类型?
9. 顺序消息是怎么实现的?
原理:同一业务 ID 的消息发送到同一个 Queue,消费者单线程顺序消费。
关键点:
- 发送端:MessageQueueSelector 保证同一 Key 发到同一 Queue
- 消费端:使用 MessageListenerOrderly 单线程消费
10. 延迟消息是怎么实现的?
延迟级别:1s、5s、10s、30s、1m、2m、3m...2h(共18级)
11. 事务消息的原理?
三个阶段:
- 发送半消息(对消费者不可见)
- 执行本地事务
- 根据事务结果提交或回滚
四、高可用与可靠性
12. 如何保证消息不丢失?
解决方案:
- 生产端:同步发送 + 失败重试
- Broker:同步刷盘 + 主从同步双写
- 消费端:业务处理成功后再提交 Offset
13. 如何保证消息不重复消费?
消息重复原因:
- 生产者重试
- 消费者重试
- Rebalance
解决方案:业务幂等
// 方案1:数据库唯一键
INSERT INTO orders ... ON DUPLICATE KEY UPDATE ...
// 方案2:Redis 去重
if (redis.setnx("msg:" + msgId, "1")) {
processMessage(msg);
}14. 消费失败怎么处理?
重试机制:
- 默认重试 16 次
- 重试间隔递增:10s、30s、1m...2h
- 超过重试次数进入死信队列(%DLQ%ConsumerGroup)
15. 主从同步有哪些模式?
| 模式 | 说明 | 可靠性 | 性能 |
|---|---|---|---|
| 同步双写 | Master 和 Slave 都写成功才返回 | 高 | 低 |
| 异步复制 | Master 写成功即返回 | 中 | 高 |
五、性能优化
16. 消息堆积怎么处理?
排查步骤:
- 检查消费者是否正常
- 检查消费逻辑是否有阻塞
- 检查消费者数量是否足够
解决方案:
- 增加消费者数量(不超过 Queue 数量)
- 增加消费线程数
- 批量消费
- 临时扩容 Queue
17. 如何提升消息吞吐量?
生产端:
- 批量发送
- 异步发送
- 增加 Producer 实例
消费端:
- 增加消费者数量
- 增加消费线程
- 批量消费
- 优化业务逻辑
Broker:
- 异步刷盘
- 增加 Queue 数量
18. RocketMQ 用了哪些零拷贝技术?
mmap 内存映射:
- 将文件映射到内存
- 减少用户态和内核态的数据拷贝
- CommitLog 和 ConsumeQueue 都使用 mmap
六、对比与选型
19. RocketMQ vs Kafka vs RabbitMQ?
| 特性 | RocketMQ | Kafka | RabbitMQ |
|---|---|---|---|
| 开发语言 | Java | Scala | Erlang |
| 单机吞吐 | 10万级 | 100万级 | 万级 |
| 延迟 | ms级 | ms级 | us级 |
| 消息可靠性 | 高 | 高 | 高 |
| 事务消息 | 支持 | 不支持 | 不支持 |
| 延迟消息 | 支持 | 不支持 | 支持(插件) |
| 适用场景 | 业务消息 | 日志/大数据 | 复杂路由 |
20. 什么场景选择 RocketMQ?
- 需要事务消息
- 需要延迟消息
- 需要消息轨迹追踪
- 金融级可靠性要求
- 阿里系技术栈
七、实战问题
21. 如何设计一个订单超时取消功能?
22. 如何保证消息顺序性?
场景:订单状态变更必须按顺序处理
方案:
- 同一订单的消息发送到同一 Queue
- 使用 MessageQueueSelector 按 OrderId 路由
- 消费端使用 MessageListenerOrderly
// 发送端
producer.send(msg, (mqs, msg, arg) -> {
int index = Math.abs(arg.hashCode()) % mqs.size();
return mqs.get(index);
}, orderId);
// 消费端
consumer.registerMessageListener(new MessageListenerOrderly() {...});23. 分布式事务怎么用 RocketMQ 实现?
场景:下单扣库存,保证数据一致性
// 1. 发送事务消息
TransactionSendResult result = producer.sendMessageInTransaction(msg, null);
// 2. 执行本地事务
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
try {
orderService.createOrder();
return LocalTransactionState.COMMIT_MESSAGE;
} catch (Exception e) {
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
// 3. 事务回查
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
Order order = orderService.getOrder(msg.getKeys());
return order != null ? COMMIT_MESSAGE : ROLLBACK_MESSAGE;
}面试技巧
- 理解原理:不要死记硬背,理解为什么这样设计
- 结合场景:用实际业务场景说明问题
- 对比分析:能说出不同方案的优缺点
- 源码加分:了解关键源码实现会加分