RocketMQ 面试核心知识点总结

一、消息不丢失机制

1. 消息丢失的核心环节

消息链路中 4 个关键丢失风险点,跨网络传输和缓存异步刷盘是主要场景:

2. 生产者端防丢失方案

(1)发送确认机制
发送方式 特点 代码示例
单向发送 效率高,可能丢消息 producer.sendOneway(msg);
同步发送 安全可靠,效率低 SendResult result = producer.send(msg, 20000);
异步发送 安全与效率平衡 producer.send(msg, new SendCallback() {<br>@Override<br>public void onSuccess(SendResult res) {}<br>@Override<br>public void onException(Throwable e) {}<br>});
(2)事务消息机制(RocketMQ 特有)

核心流程:

适用场景:电商订单创建与支付确认等分布式事务场景

3. Broker 端防丢失方案

(1)刷盘机制
  • 同步刷盘(SYNC_FLUSH):写入日志即调用 fsync,消息不丢失但 IO 压力大
  • 异步刷盘(ASYNC_FLUSH):定期刷盘,性能好但断电可能丢缓存消息
  • 核心配置:flushDiskType=SYNC_FLUSH(生产环境推荐)
(2)主从同步机制
集群类型 同步方式 数据安全性 切换逻辑
普通集群 同步 Master(SYNC_MASTER)/ 异步 Master(ASYNC_MASTER) 高(SYNC_MASTER) Master 挂了不自动切换
DLedger 集群 Raft 协议多数派确认 极高 自动选举 Leader,数据一致性优先

关键差异:Kafka Leader 崩溃后新 Leader 以自身数据为准,可能丢失未同步消息;RocketMQ Master 重启后继续同步未同步数据,不丢失

4. 消费者端防丢失方案

  • 核心原则:先处理消息,再提交消费确认

  • 风险场景:异步处理消息时提前返回成功状态

    // 错误示例(可能丢失消息)
    consumer.registerMessageListener((msgs, context) -> {
    new Thread(() -> {
    // 异步处理业务,可能未执行完就返回成功
    }).start();
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    });

    // 正确示例(同步处理)
    consumer.registerMessageListener((msgs, context) -> {
    // 同步处理业务逻辑
    processBusiness(msgs);
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    });

  • 重试机制:未收到确认时 Broker 会重复投递,RocketMQ 通过 Offset,RabbitMQ 通过重新入队

5. 极端场景(MQ 集群全挂)处理

  • 降级方案:生产者发送失败时写入本地缓存(如 Redis、文件)
  • 恢复机制:独立线程循环重试发送缓存消息,MQ 恢复后自动补送

6. 零丢失方案总结(trade-off)

环节 方案 代价
生产者 同步发送 + 重试 降低吞吐
Broker 同步刷盘 + DLedger 集群 IO / 网络负担增加
消费者 同步处理 + 确认 无法异步提升效率
集群故障 降级缓存 增加存储成本

二、消息顺序性保障

1. 核心概念

  • 局部有序:同一业务维度(如同一订单)的消息有序(实际业务常用)
  • 全局有序:整个 Topic 的消息有序(极少场景需要,性能极差)

2. 实现机制(RocketMQ)

两大关键:

  1. 生产者:通过分区算法将同业务标识消息写入同一 MessageQueue
  2. 消费者:单个 Consumer 线程对应单个 MessageQueue,串行消费

3. 不同 MQ 对比

MQ 产品 顺序性保障方式 特点
RocketMQ 分区绑定 + 单线程消费 支持局部有序,配置灵活
Kafka 单 Partition 单线程消费 天生支持局部有序
RabbitMQ 单 Queue 对应单 Consumer 经典队列需手动保证绑定关系

三、消息幂等性处理

1. 幂等性定义

  • 多次处理同一消息,业务结果一致(不重复创建订单、不重复扣款)

2. 生产者端幂等

(1)RocketMQ 实现
  • 自动生成唯一messageId(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX)
  • Broker 通过该 ID 判断重复消息
(2)Kafka 实现
  • 开启幂等性配置(默认开启),核心机制:
    • PID:生产者唯一标识
    • Sequence Number:每个 PID+Partition 的单调递增序号
    • Broker 仅接收序号 = 当前 SN+1 的消息

3. 消费者端幂等

(1)去重依据(优先级)
  1. 业务唯一标识(推荐):如订单 ID、支付流水号(通过msg.setKey(业务ID)设置)
  2. MQ 内置唯一 ID:messageId(批量 / 事务消息场景可能失效)
(2)实现方式
复制代码
// 伪代码示例
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs) {
    for (MessageExt msg : msgs) {
        String businessId = msg.getKey(); // 订单ID
        // 1.查缓存/数据库判断是否已处理
        if (isProcessed(businessId)) {
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }
        // 2.处理业务逻辑
        processBusiness(msg);
        // 3.标记为已处理(缓存/数据库)
        markAsProcessed(businessId);
    }
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
(3)异常处理
  • 重试队列:重复投递的消息进入重试队列(%RETRY%消费者组名)
  • 死信队列:多次重试失败进入死信队列(%DLQ%消费者组名),需手动调整权限后处理

四、消息积压处理

1. 积压风险

  • RocketMQ/Kafka:日志文件过期会删除未消费消息
  • RabbitMQ:经典队列积压严重影响服务端性能

2. 处理方案

(1)临时扩容(快速见效)
  • 核心限制:Consumer 实例数 ≤ MessageQueue 数(RocketMQ/Kafka)
  • 操作步骤:
    1. 增加 Consumer 实例(不超过 Queue 数)
    2. 优化 Consumer 消费逻辑(关闭非核心业务、异步处理非关键步骤)
(2)分流处理(大量积压时)
  • 操作步骤:
    1. 创建新 Topic,配置更多 MessageQueue
    2. 部署临时消费者,仅负责将旧 Topic 消息转存到新 Topic
    3. 新 Topic 部署足够多 Consumer 实例快速消费
    4. 消费完成后恢复正常架构

五、常见面试题及参考答案

1. RocketMQ 如何保证消息不丢失?

  • 生产者:使用同步发送 + 重试机制,关键场景用事务消息
  • Broker:配置同步刷盘 + DLedger 高可用集群
  • 消费者:同步处理消息后提交确认,避免异步提前返回成功
  • 极端情况:降级缓存 + 后台重试发送

2. 如何保证消息的顺序性?

  • 实现局部有序:生产者将同业务标识消息写入同一 MessageQueue,消费者单线程消费单个 MessageQueue
  • 不推荐全局有序:Topic 只配置 1 个 Queue,性能极差,无实际业务价值

3. 如何解决消息重复消费问题?

  • 生产者端:RocketMQ 通过唯一 messageId 去重,Kafka 通过 PID+SequenceNumber 保证幂等
  • 消费者端:基于业务唯一标识(如订单 ID)做幂等处理,通过缓存 / 数据库记录处理状态

4. 消息积压了怎么处理?

  • 短期:增加 Consumer 实例(不超过 Queue 数),优化消费逻辑
  • 长期:创建多 Queue 新 Topic,临时分流积压消息,批量快速消费

5. RocketMQ 的事务消息原理是什么?

  • 两阶段提交:先发送半消息,执行本地事务后再确认 Commit/Rollback
  • 兜底机制:Broker 定期回查本地事务状态,避免事务结果丢失

6. RocketMQ 与 Kafka 在消息安全上的核心差异?

  • 主从同步:RocketMQ Master 挂了不切换,重启后同步未同步数据;Kafka 会选举新 Leader,丢失未同步消息
  • 设计初衷:RocketMQ 源于金融场景,优先数据安全;Kafka 源于日志收集,优先服务可用性
相关推荐
夏幻灵5 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
时间的拾荒人10 小时前
Qt 界面优化:绘图详解 —— 从基础图形到图片处理
开发语言·qt·面试
沐言人生12 小时前
又一个神级考公脑库-22,375篇真题终于按考点整理了
后端·面试
for_ever_love__12 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
救救孩子把13 小时前
Agent面试题-记忆治理-上下文-多Agent协作与工程落地
面试·agent·多agent·agent记忆·agent面试题·上下文治理
泡干脆面就番茄13 小时前
HDFS读写流程与MapReduce原理深度解析(面试高频考点)
hdfs·面试·mapreduce
bksczm14 小时前
0基础面试3
面试·职场和发展
老王爱玩车16 小时前
动态内存管理
c语言·开发语言·学习·面试
海绵宝宝转agent16 小时前
2026-10-9 leetcode100刷题+面经整理
笔记·算法·面试
JAVA面经实录91717 小时前
Java高级后端 · 全套面试通关手册(线上故障排查)
java·jvm·面试