MQ消息丢失、重复、积压问题如何解决
(附:2025 Java面试宝典下载)
为什么消息问题必考?
面试官最爱问MQ问题,尤其消息丢失、消息重复、消息积压三大痛点。搞不定这些,分布式系统根本玩不转。今天咱们用实战思路拆解解决方案!

消息中间件核心问题示意图
一、消息丢失:数据去哪儿了?
核心原因:生产者到MQ、MQ持久化、消费者处理 这三个环节都可能丢数据。
解决消息丢失的实战方案:
-
生产者端双重保险
- 开启
confirm机制(RabbitMQ)或ACK(Kafka) - 本地消息表 + 定时重发(比如订单创建场景)
- 开启
-
MQ持久化别偷懒
// 错误示范(RabbitMQ) channel.basicPublish("", "non-persistent-queue", null, message.getBytes()); // 正确姿势 AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().deliveryMode(2).build(); channel.basicPublish("", "persistent-queue", props, message.getBytes()); -
消费者手动ACK
关掉自动提交(Kafka的enable.auto.commit=false),业务逻辑成功后才提交offset
二、消息重复:一条数据被消费N次
根本原因:网络重发、消费者重启、offset提交延迟都会导致消息重复。
根治重复消息三板斧:
-
幂等设计是底线
- 数据库用唯一约束(比如订单号+状态)
- Redis的
SETNX做防重(key=业务标识+消息ID)
-
MQ自带去重神器
- RocketMQ的
MessageId或业务键去重 - Kafka开启幂等生产者(
enable.idempotence=true)
- RocketMQ的
-
版本号控制
给消息加版本号,旧版本直接丢弃:UPDATE order SET status=‘paid’, version=3 WHERE id=100 AND version=2;
三、消息积压:十万火急的处理方案

消息积压紧急处理流程
消息积压的救火步骤:
-
快速扩容消费者
- 紧急加机器,消费者组横向扩容
- 线程池调参(注意别打垮DB)
-
降级非核心业务
- 暂停次要消息的消费(比如日志统计)
- 写死数据快速返回(牺牲一致性保可用性)
-
死信队列转移战场
把积压消息转到新Topic,用离线集群慢慢消化 -
终极手段:消息回溯
Kafka重置offset到最早位置(慎用!可能重复消费)
面试怎么答才能加分?
- 先说消息丢失的"三段防御链":生产者确认+MQ持久化+手动ACK
- 强调消息重复必须用幂等 + 去重机制组合拳
- 消息积压分三步:扩容->降级->离线处理
📌 加分技巧:举例说明你在项目中如何落地这些方案,比如:"我们订单系统用Redis的
SETNX实现了毫秒级去重"
最后送你两把利器
- 2025 Java面试宝典:覆盖大厂高频MQ考点
- 面试鸭会员福利:通过面试鸭返利网购买会员可返利25元,用省下的钱喝杯咖啡继续学!

记住:解决消息丢失靠确认机制,解决消息重复靠幂等设计,搞定消息积压靠弹性扩缩容。把这套方法论吃透,面试官绝对眼前一亮!


