我这里不再详细讲解什么是幂等性以及常见的解决方案,因为网上已经有很多相关内容。幂等性问题的解决方法需要根据具体场景来定。本文主要分享我遇到的实际场景和解决方案,希望对你有所帮助。
今天早上起床时,发现群里有小伙伴遇到了一个问题:接口被多次重复调用,导致请求成功后发生了幂等性问题。
看到这里,可能很多人都会疑惑:什么是幂等性?其实,这个概念对于不少开发者来说可能很陌生。为了让大家更清楚,我特别引用了 GPT 的解释,供大家参考。
幂等性问题是指在某些情况下,接口或操作被多次重复调用,可能会导致预期之外的副作用或错误行为,主要是因为未正确处理幂等性。
幂等性的本质是:无论某个操作被执行多少次,其最终的效果应与执行一次时相同。
具体问题场景
- 重复提交订单
用户因网络延迟或误操作,重复点击“提交订单”按钮,导致订单重复创建。 - 支付扣款重复
支付接口未正确处理幂等性时,可能因超时或重试机制,导致用户被扣款多次。 - 库存操作不一致
接口多次调用导致库存重复扣减,最终数据与实际情况不符。
嗯,说到这里,我就不卖关子了,我之前遇到的情况就是某单机设备由于并发我的http接口,导致重复生成多条调度任务,尽管是方法内有防呆有事务也没有用。
为什么有防呆有事务也没有用呢?
由于事务的机制比较复杂,我这里结合当前的场景简单说明一下。多线程高并发请求时,每个线程都会创建独立的事务。事务的职责是保证单个线程内的操作具备原子性、一致性、隔离性和持久性(ACID)。然而,事务无法避免多个线程同时读取相同数据并分别进入事务的情况。
在这种情况下,即使每个事务都能保证其内部操作的正确性,如果多个事务同时通过前置条件检查(如数据是否存在),就可能出现重复生成调度任务的情况。因此,事务在面对这种高并发场景时是无能为力的。
其实简单的思路那就是加锁,而我这边就加上异步锁后,相同任务名称的请求将只能同时处理一个,其他请求需要等待,但不会影响到其他任务名称的请求。
除此之外,其实还可以用线程字典去处理这个问题,大概代码如下
本文展示的例子都有代码,可以去代码仓库看:https://github.com/peijiehuang/IdempotencySolution