RocketMQ 常见面试题汇总

一、RocketMQ 基础

1. RocketMQ 是什么?

复制代码
# 核心特点:
- 阿里开源,Apache顶级项目
- 分布式消息中间件
- 高可用、高吞吐、低延迟
- 支持发布订阅、顺序消息、事务消息
- 支持消息轨迹、消息过滤

2. RocketMQ 架构

复制代码
# 核心组件:
1. NameServer: 无状态注册中心
   - 服务发现与路由管理
   - 轻量级,集群部署
   
2. Broker: 消息存储和转发
   - 主从架构,支持同步/异步复制
   - 消息存储、查询、消费队列管理
   
3. Producer: 消息生产者
   - 与NameServer建立长连接
   - 从NameServer获取路由信息
   
4. Consumer: 消息消费者
   - Push/Pull两种模式
   - 集群/广播两种消费模式

3. RocketMQ 与其他MQ对比

特性 RocketMQ Kafka RabbitMQ ActiveMQ
设计目标 金融级 日志处理 企业级 传统消息
吞吐量 极高 极高 中等
延迟 毫秒级 毫秒级 微秒级 毫秒级
可用性 非常高 中等
事务消息 支持 不支持 支持 支持
消息顺序 支持 支持 不支持 支持
消息追溯 支持 支持 有限 有限
成熟度 极高 极高

二、NameServer

1. NameServer 作用

复制代码
# 核心功能:
1. 服务注册:Broker启动时注册
2. 服务发现:Producer/Consumer获取路由
3. 心跳检测:监控Broker存活状态
4. 路由管理:维护Topic-Broker映射

# 特点:
- 无状态设计,可水平扩展
- 数据存储在内存
- 通过心跳维持数据
- 部署奇数台(2n+1)

2. NameServer 工作流程

复制代码
// 1. Broker注册
Broker → NameServer: 注册Topic、Broker、Queue信息
// 2. Producer/Consumer查询
Producer → NameServer: 查询Topic路由
// 3. 心跳机制
Broker → NameServer: 每30秒发送心跳
// 4. 故障检测
NameServer: 120秒无心跳,剔除Broker

三、Broker

1. Broker 架构

复制代码
# 核心模块:
1. Remoting: 网络通信层
2. Client Manager: 客户端管理
3. Store Service: 存储服务
4. HA Service: 高可用服务
5. Index Service: 索引服务

# 存储结构:
Broker
├── CommitLog    # 所有消息顺序存储
├── ConsumeQueue # 逻辑消费队列
├── IndexFile    # 消息索引
└── Config       # 配置信息

2. 消息存储机制

复制代码
# 存储流程:
1. 消息写入CommitLog(顺序写)
2. 异步构建ConsumeQueue
3. 异步构建IndexFile

# 文件结构:
CommitLog: 1GB固定大小,顺序写入
ConsumeQueue: 30万条记录,固定大小
IndexFile: 哈希索引,支持快速查找

3. 主从复制

复制代码
# 复制方式:
1. 同步复制:主从都写成功返回ACK
2. 异步复制:主成功即返回

# 配置:
brokerRole:
  - ASYNC_MASTER   # 异步复制主节点
  - SYNC_MASTER    # 同步复制主节点
  - SLAVE          # 从节点

四、Producer

1. 生产者类型

复制代码
// 1. 普通生产者
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.send(message);

// 2. 事务消息生产者
TransactionMQProducer producer = new TransactionMQProducer("TranProducerGroup");
producer.setTransactionListener(new TransactionListenerImpl());

// 3. 延迟消息生产者
message.setDelayTimeLevel(3);  // 延迟级别

2. 发送模式

复制代码
// 1. 同步发送
SendResult result = producer.send(message);

// 2. 异步发送
producer.send(message, new SendCallback() {
    public void onSuccess(SendResult result) {}
    public void onException(Throwable e) {}
});

// 3. 单向发送
producer.sendOneway(message);

3. 消息类型

复制代码
// 1. 普通消息
Message msg = new Message("Topic", "Tag", "Key", body);

// 2. 顺序消息
MessageQueueSelector selector = new MessageQueueSelector() {
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        Integer id = (Integer) arg;
        int index = id % mqs.size();
        return mqs.get(index);
    }
};
producer.send(msg, selector, orderId);

// 3. 事务消息
TransactionSendResult result = producer.sendMessageInTransaction(msg, null);

// 4. 定时/延迟消息
msg.setDelayTimeLevel(3);  // 延迟10秒

五、Consumer

1. 消费者类型

复制代码
// 1. 推模式(推荐)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
consumer.registerMessageListener(new MessageListenerConcurrently() {
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeConcurrentlyContext context) {
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

// 2. 拉模式
DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("PullConsumerGroup");

2. 消费模式

复制代码
// 1. 集群消费(默认)
consumer.setMessageModel(MessageModel.CLUSTERING);

// 2. 广播消费
consumer.setMessageModel(MessageModel.BROADCASTING);

3. 消费进度管理

复制代码
# 进度存储:
- 集群模式:Broker存储
- 广播模式:本地存储

# 重置消费位点:
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
// CONSUME_FROM_LAST_OFFSET   最后位置
// CONSUME_FROM_FIRST_OFFSET  开始位置
// CONSUME_FROM_TIMESTAMP     指定时间

六、消息存储与清理

1. 存储流程

复制代码
# 写入流程:
1. Producer发送消息到Broker
2. Broker写入CommitLog(顺序写)
3. 异步构建ConsumeQueue
4. 异步构建IndexFile

# 读取流程:
1. Consumer发送拉取请求
2. Broker查询ConsumeQueue获取CommitLog偏移量
3. 从CommitLog读取消息
4. 返回给Consumer

2. 文件清理策略

复制代码
# 清理条件:
1. 文件过期:默认72小时
2. 磁盘空间不足
3. 手动触发清理

# 配置:
fileReservedTime=72        # 文件保留时间(小时)
deleteWhen=04             # 清理时间(凌晨4点)
diskMaxUsedSpaceRatio=75  # 最大磁盘使用率

七、顺序消息

1. 顺序消息原理

复制代码
# 全局顺序:
- Topic只有一个队列
- 严格保证全局顺序
- 性能较低

# 分区顺序:
- 同一业务ID的消息发到同一队列
- 同一队列内保证顺序
- 使用MessageQueueSelector

2. 顺序消费实现

复制代码
// 生产者
producer.send(msg, new MessageQueueSelector() {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        Long orderId = (Long) arg;
        long index = orderId % mqs.size();
        return mqs.get((int) index);
    }
}, orderId);

// 消费者(顺序监听器)
consumer.registerMessageListener(new MessageListenerOrderly() {
    @Override
    public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeOrderlyContext context) {
        // 顺序处理
        return ConsumeOrderlyStatus.SUCCESS;
    }
});

八、事务消息

1. 事务消息流程

复制代码
# 两阶段提交:
1. 发送half消息
2. 执行本地事务
3. 提交/回滚消息

# 状态检查:
- Broker定时检查half消息状态
- 回调生产者检查事务状态

2. 事务消息实现

复制代码
// 事务监听器
public class TransactionListenerImpl implements TransactionListener {
    
    // 执行本地事务
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
            // 执行本地业务
            boolean success = doBusiness();
            return success ? LocalTransactionState.COMMIT_MESSAGE 
                          : LocalTransactionState.ROLLBACK_MESSAGE;
        } catch (Exception e) {
            return LocalTransactionState.UNKNOW;
        }
    }
    
    // 检查本地事务状态
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        // 检查业务状态
        return checkBusinessStatus() ? LocalTransactionState.COMMIT_MESSAGE
                                    : LocalTransactionState.ROLLBACK_MESSAGE;
    }
}

九、延迟消息

1. 延迟级别

复制代码
# 18个固定级别:
1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

# 实现原理:
1. 发送延迟消息
2. Broker将消息存入SCHEDULE_TOPIC_XX队列
3. 定时任务扫描到期消息
4. 投递到目标Topic

2. 自定义延迟

复制代码
// 不支持自定义延迟时间
// 可通过以下方式模拟:
1. 使用定时任务+普通消息
2. 使用Redis ZSet实现
3. 使用时间轮算法

十、消息过滤

1. 过滤方式

复制代码
# 1. Tag过滤(推荐)
- 一个消息一个Tag
- 消费者订阅Tag表达式
- 如: TagA || TagB

# 2. SQL过滤
- 基于消息属性过滤
- 支持SQL92语法
- 如: a > 5 AND b = 'abc'

# 3. 类过滤
- 实现MessageFilter接口
- 完全自定义过滤逻辑

2. Tag过滤示例

复制代码
// 生产者
Message msg = new Message("Topic", "TagA", "Key", body);

// 消费者
consumer.subscribe("Topic", "TagA || TagB");

// 不推荐:* 表示订阅所有Tag
consumer.subscribe("Topic", "*");

十一、高可用与负载均衡

1. Producer负载均衡

复制代码
// 默认策略:轮询
List<MessageQueue> mqs = producer.fetchPublishMessageQueues("Topic");
MessageQueue mq = mqs.get(index % mqs.size());

// 自定义策略
producer.send(msg, new MessageQueueSelector() {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        // 自定义选择逻辑
        return mqs.get(hash(arg) % mqs.size());
    }
}, shardingKey);

2. Consumer负载均衡

复制代码
# 集群模式负载均衡:
1. 获取Topic所有队列
2. 获取消费者组所有消费者
3. 平均分配队列
4. 每20秒重新平衡

# 分配策略:
- 平均分配(默认)
- 环形分配
- 机房就近分配
- 一致性哈希分配

3. Broker高可用

复制代码
# 主从架构:
- 一主多从
- 同步/异步复制
- 自动故障转移

# 部署建议:
- 至少2主2从
- 跨机房部署
- 监控报警

十二、消息轨迹

1. 轨迹数据

复制代码
# 记录信息:
1. 生产者轨迹
   - 发送时间
   - 发送状态
   - 发送IP
   
2. 消费者轨迹
   - 消费时间
   - 消费状态
   - 消费IP
   - 重试次数

2. 轨迹配置

复制代码
# 开启轨迹
traceTopicEnable=true
traceTopicName=RMQ_SYS_TRACE_TOPIC

# 轨迹存储
- 默认存储到Broker
- 可自定义存储
- 支持可视化查询

十三、性能优化

1. 生产者优化

复制代码
// 1. 批量发送
List<Message> messages = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    messages.add(new Message("Topic", "Tag", "Key", body));
}
SendResult result = producer.send(messages);

// 2. 压缩消息
message.setCompressed(true);

// 3. 合理设置Topic队列数
// 建议:队列数 = 生产者数 * 消费者数

2. 消费者优化

复制代码
// 1. 批量消费
consumer.setConsumeMessageBatchMaxSize(32);

// 2. 并发消费
consumer.setConsumeThreadMin(20);
consumer.setConsumeThreadMax(64);

// 3. 拉取批量
consumer.setPullBatchSize(32);

3. Broker优化

复制代码
# 1. 存储优化
flushDiskType=ASYNC_FLUSH  # 异步刷盘
flushCommitLogLeastPages=4  # 最少页数

# 2. 内存优化
mappedFileSizeCommitLog=1073741824  # 1GB
mappedFileSizeConsumeQueue=300000  # 30万条

# 3. 网络优化
sendMessageThreadPoolNums=16
pullMessageThreadPoolNums=16

十四、监控与运维

1. 监控指标

复制代码
# 关键指标:
1. 消息堆积
   - 监控Topic消费延迟
   
2. 生产/消费TPS
   - 监控消息吞吐量
   
3. 系统资源
   - CPU、内存、磁盘、网络
   
4. 错误率
   - 发送失败率
   - 消费失败率

2. 运维命令

复制代码
# 1. 集群状态
mqadmin clusterList -n localhost:9876

# 2. Topic状态
mqadmin topicStatus -n localhost:9876 -t TopicTest

# 3. 消费进度
mqadmin consumerProgress -n localhost:9876 -g ConsumerGroup

# 4. 消息查询
mqadmin queryMsgById -n localhost:9876 -i 0A9A003F00002A9F00000000000003B4

# 5. 发送消息
mqadmin sendMsgStatus -n localhost:9876 -t TopicTest -p "hello" -k "key"

十五、常见问题与解决方案

1. 消息丢失

复制代码
# 可能原因:
1. 异步刷盘丢失
2. 主从复制丢失
3. 消费者处理异常

# 解决方案:
1. 同步刷盘 + 同步复制
2. 事务消息
3. 消费端幂等处理
4. 消息轨迹追踪

2. 消息重复

复制代码
# 可能原因:
1. 生产者重试
2. 消费者重试
3. Broker重投

# 解决方案:
1. 消费端幂等处理
2. 使用全局唯一ID
3. 记录已处理消息

3. 消息堆积

复制代码
# 处理方案:
1. 增加消费者实例
2. 提高消费能力
3. 临时Topic分流
4. 跳过堆积消息
5. 设置死信队列

十六、高级特性

1. 消息重试

复制代码
// 顺序消息不重试
// 普通消息重试机制:
// 重试次数:16次
// 重试间隔:越来越长
// 重试Topic:%RETRY%ConsumerGroup

// 消费失败处理
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
    ConsumeConcurrentlyContext context) {
    try {
        // 处理消息
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    } catch (Exception e) {
        // 返回RECONSUME_LATER会重试
        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
    }
}

2. 死信队列

复制代码
# 死信Topic:
%DLQ%ConsumerGroup

# 进入条件:
1. 最大重试次数后仍失败
2. 默认重试16次

# 处理:
1. 监控死信队列
2. 人工干预处理
3. 重新投递

十七、RocketMQ 5.0 新特性

1. 轻量级队列

复制代码
# 特点:
- 更轻量的消费进度管理
- 支持更高并发
- 简化运维

2. 多副本机制

复制代码
# DLEDGER模式:
- 基于Raft协议
- 自动选主
- 强一致性

3. 云原生支持

复制代码
# 特性:
- 容器化部署
- 弹性伸缩
- 服务网格集成

十八、常见面试题

1. 基础问题

复制代码
Q1: RocketMQ如何保证消息不丢失?
A:
1. 生产者:同步发送+重试
2. Broker:同步刷盘+同步复制
3. 消费者:正确消费后确认

Q2: NameServer在集群中作用?
A:
1. 服务注册与发现
2. 路由信息管理
3. 心跳检测
4. 无状态设计,可水平扩展

Q3: CommitLog和ConsumeQueue区别?
A:
- CommitLog:物理存储,所有消息顺序写入
- ConsumeQueue:逻辑队列,存储消息在CommitLog的偏移

2. 进阶问题

复制代码
Q4: 如何实现顺序消息?
A:
1. 生产者:相同业务ID发送到同一队列
2. 消费者:顺序消费同一队列
3. 使用MessageQueueSelector和MessageListenerOrderly

Q5: 事务消息实现原理?
A:
1. 发送half消息
2. 执行本地事务
3. 提交/回滚消息
4. Broker定时检查未完成事务

Q6: 如何解决消息堆积?
A:
1. 增加消费者实例
2. 提高批量消费大小
3. 优化消费逻辑
4. 临时扩容Topic队列
5. 设置死信队列

3. 实战问题

复制代码
Q7: 如何设计消息幂等性?
A:
1. 消息唯一ID
2. 业务状态检查
3. 数据库唯一约束
4. Redis防重表
5. 分布式锁

Q8: 如何选择同步/异步复制?
A:
- 同步复制:金融场景,强一致性
- 异步复制:日志场景,高性能
- 根据业务容忍度选择

Q9: 如何监控RocketMQ集群?
A:
1. 自带监控命令
2. 集成Prometheus
3. 使用RocketMQ-Exporter
4. 配置告警规则
5. 监控关键指标

面试准备建议

  1. 深入理解架构设计原理

  2. 掌握消息存储和流转机制

  3. 熟悉各种消息类型的使用场景

  4. 了解高可用和负载均衡策略

  5. 准备实际项目中的问题解决经验

  6. 关注新版本特性变化

  7. 动手搭建和配置集群

高频考点

  • RocketMQ核心组件与架构

  • 消息存储机制(CommitLog/ConsumeQueue)

  • 顺序消息实现原理

  • 事务消息两阶段提交

  • 消息高可用方案

  • 消息过滤与路由

  • 性能优化策略

  • 常见问题排查与解决

相关推荐
隔叶听风13 小时前
RocketMQ 与 Kafka 长轮询详解
数据库·kafka·rocketmq
C1829818257514 小时前
Rocketmq
java·rocketmq·java-rocketmq
czlczl2002092515 小时前
RocketMQ如何实现与其它事务的一致性
rocketmq
yyongsheng1 天前
微服务项目整合rocketMq
微服务·架构·rocketmq
阿里云云原生9 天前
秒触达、零资损:亲宝宝基于 RocketMQ 支撑千万家庭实时互动与成长记录
serverless·rocketmq
初次攀爬者10 天前
RocketMQ 消息可靠性保障与堆积处理
后端·消息队列·rocketmq
用户83071968408210 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者10 天前
RocketMQ 集群介绍
后端·消息队列·rocketmq
初次攀爬者10 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq