Products
GG网络技术分享 2026-04-16 17:27 0
哎,说起消息队列的幂等性啊,那真是个让人头疼的问题!当初我刚接手项目的时候,就主要原因是没考虑到这块儿,导致线上数据混乱了好一阵子。 小丑竟是我自己。 用户反馈订单重复创建,财务那边天天找我核对账单… 那滋味儿,简直生不如死!所以今天就来好好唠唠这个话题,争取把这块儿讲透彻了。
简单就是你一条消息,无论被消费者处理多少次后来啊都应该是一样的。就好像你给银行转账100块钱,不管这个转账请求发几次你的账户到头来扣掉的钱都应该是100块。不能主要原因是网络抖动或者消费者BUG导致钱被扣了两次、三次… 那可就闹大了!

基本上... 消息队列中如何保证幂等性.可以看出,消息发送和消息消费两个步骤是有可能产生消息不幂等的问题。.步骤4:消息队列服务 MQ-Server 将消息发给给消费端 MQ-Client Consumer.
想想看, 如果你的系统没有做好幂等性处理,那么在以下几种情况下就很容易出问题:
这些情况都会导致同一条消息被多次处理,从而造成数据的不一致。
一开始我也想过最简单的办法——先判断状态再更新。比如对于一个订单创建的请求,先查询一下这个用户有没有已经创建过订单了。如果没有的话就创建订单;如果有的话就直接返回成功。但是!这种方法在高并发场景下很容易出问题,太治愈了。。
以处理用户消费订单业务为例, 如果用户在同一时间发起了多次创建订单请求,那么这时多个请求发送过来很简单,我们可以先判断当前用户订单状态是否已经更新如果已经更新了那么我们就没必要再进行更新了,但是这里 记住... 会有一个问题,如果订单处理业务要耗费很长时间,在并发场景下多个请求一边打到服务器上,就有可能出现其实当前正在更新状态,但是其实吧判断并不生效的后来啊,所以呢这种最简朴的方法在业务繁琐的场景下并不奏效
然后我就想到了加锁。在处理业务之前先获取一把锁,这样就能保证只有一个线程能施行业务逻辑了。 体验感拉满。 但是加锁也会带来问题——性能下降!在高并发的场景下加锁会导致大量的线程阻塞等待锁释放。
人间清醒。 就拿锁的两个分支乐观锁与悲观锁举例,如果我们使用悲观锁,在第一个请求来的时候就直接锁住整个业务,那么当其他请求过来时,就必须要等待,这样降低了其他服务施行的性能,得不偿失;而如果我们使用乐观锁,在第一个请求过来时,每次都施行,为了保证业务只能施行一次,我们必须要加一些版本号的字段等保证这个业务不会被重复施行,这样做加大了代码的复杂度
| 解决方案 | 优点 | 缺点 |
|---|---|---|
| 悲观锁 | 简单易懂 | 并发性能差 |
| 乐观锁 | 并发性能相对较好 | 代码复杂度高 |
| 数据库事务+插入唯一记录表 | 可以有效防止重复操作 | 增加了数据库压力 |
为了解决上述问题呢? 我尝试了一种更复杂的方案——数据库事务+插入唯一记录表. 我们额外建立一张数据库表为消息表,当我们施行业务代码时按照如下流程施行:
| 产品名称 | 特点 | 适用场景 |
|---|---|---|
| Kafka | 高吞吐量、 分布式、持久化 | 日志收集、流式计算、事件驱动架构 |
| RabbitMQ | 灵活、可靠、支持多种协议 | 企业级应用、异步任务处理、复杂路由需求 |
| RocketMQ | 高性能、低延迟、金融级可靠性 | 电商交易系统、金融支付系统、实时风控系统 |
说了这么多方法吧... 但其实我要表达的是:**消息队列本身是无法保 又爱又恨。 证消费幂等的**! 它只能尽力保证消息至少到达一次或者最多到达一次。
总之啊!要实现真正的幂等性还得靠你自己去设计合适的方案啦~希望我的分享能给你带来一些启发和帮助!祝你好运!!!
Demand feedback