MQ如何保证消息的幂等性
大家好,今天聊聊面试高频题——MQ如何保证消息不被重复消费,也就是消息的幂等性。作为程序员,分布式系统里消息队列用得多,但重复消费真是让人头大的问题。咱们结合实际场景拆解几种实用方案,面试时直接套用就行。

📌2025年Java面试宝典抢先看:
点我获取👉 链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g
提取码: 9b3g (会员课程更新中,建议保存)
🔍 什么是消息幂等性?
简单说就是:同一条消息无论消费多少次,结果都一致。比如支付成功通知发了两次,总不能扣用户两笔钱吧?这就是典型的MQ幂等问题场景。
💡 四种实战级MQ幂等方案
1️⃣ 唯一ID + 去重表(最常用)
核心逻辑:给每条消息绑个唯一ID(比如业务主键),消费前先查库判断是否处理过。
-- 建表语句示例
CREATE TABLE msg_unique (
id VARCHAR(64) PRIMARY KEY, -- 消息唯一ID
status TINYINT DEFAULT 0 -- 0未处理 1已处理
);
适用场景:订单支付、库存扣减等强事务操作。
⚠️ 注意:数据库压力大时考虑加缓存层(Redis SETNX),但记得设置过期时间防缓存击穿。

2️⃣ 版本号控制(乐观锁)
核心逻辑:消息体带数据版本号,消费时对比版本号是否匹配。
// 伪代码示例
if(message.version > currentData.version) {
updateData(message); // 只更新新版本数据
}
适用场景:配置更新、状态机流转(如订单状态变更)。
✅ 优势:避免数据库频繁查询,提升性能。
3️⃣ 状态机幂等
核心逻辑:业务状态设计成单向流转(如 未支付→已支付→已完成),重复消息会被状态机拦截。
# 订单状态机示例
if current_status == "PAID" and message_status == "PAID":
return # 直接忽略重复支付消息
适用场景:工单系统、审批流等有明确状态边界的业务。
4️⃣ 业务锁机制
核心逻辑:对关键资源加锁(如Redis分布式锁),确保同时只有一条消息能操作资源。
// 伪代码示例
try {
if(redis.lock("order_123")) {
processMessage(); // 处理消息
}
} finally {
redis.unlock("order_123");
}
⚠️ 坑点:锁超时时间要大于业务处理时间,避免并发冲突。
🚀 面试加分技巧
- 组合使用更保险:比如“唯一ID+状态机”双校验
- 强调最终一致性:MQ本身不保证绝对不重复,需要业务层兜底
- 提一句消息轨迹:用RocketMQ的MessageTrace功能辅助排查重复消息
💰 省💰小贴士:如果大家准备买面试鸭会员,记得通过 面试鸭返利网 下单,能返25元!直接抵扣真香~
🌟 一句话总结
MQ的幂等性本质是业务问题,根据场景选方案:高频业务用Redis+去重表,状态驱动业务用状态机,对性能要求高用版本号控制。理解了这个逻辑,面试官绝对眼前一亮!
返回 面试鸭返利网首页 解锁更多面试技巧


