外观
一句话答案
MQ 至少投递一次必有重复,幂等方案:唯一消息 ID+去重表、数据库唯一索引、乐观锁 version、业务状态机。
核心要点
方案:
| 方案 | 适用 |
|---|---|
| 唯一消息ID + Redis/DB去重 | 通用 |
| 数据库唯一索引 | INSERT场景 |
| 乐观锁(version) | UPDATE场景 |
| 状态机 | 有状态流转业务 |
原则: 消费逻辑本身做幂等,不依赖MQ去重
追问与易错
追问方向:
- 为什么 MQ 不保证 Exactly-Once?(网络不可靠 + 至少投递一次更简单可靠)
- 去重表用什么存?有什么问题?(Redis/DB,Redis 有过期风险,DB 有性能问题)
- 幂等性怎么做单元测试?
易错点:
- ❌ "让 MQ 保证不重复就行了"——MQ 只保证不丢(At Least Once),重复由消费端处理
- ❌ "唯一索引就能解决所有重复"——只适合 INSERT,UPDATE 需要乐观锁/状态机
💡 记忆锚点
幂等 = 电梯按钮按多次和按一次效果一样。MQ保证至少投递一次所以必有重复,消费端自己做幂等:INSERT用唯一索引挡重复,UPDATE用乐观锁version防覆盖,有状态流转用状态机(已支付不能再支付)。