幂等和重复支付

231 阅读3分钟

前言

幂等和重复支付,是两个不同的问题,必须得分开,不能混淆,才能理解清楚。

下面以扫码支付为例。

幂等

幂等的解决方案是:先查后改 + 锁。

先查后改

直接举例,第一次支付请求,订单号1并且支付成功。

然后,第二次请求,但是是同一笔订单,即同一个订单号。

那怎么办?

这个时候,会先查询,即根据订单号1从数据库查询订单,并且会检查订单状态是否已经支付成功,如果成功,就直接拒绝第二次请求,为什么要拒绝?因为不同的请求线程,本质是两个事务,所以这两个事务不能出现篡改同一笔订单数据的问题。这个就是幂等。

幂等的本质,针对的是同一笔订单,然后要解决同一笔订单的不同请求事务的篡改数据的问题。

先查后改,可以解决99%的问题。说白了,就是,如果是非高并发,其实先查后改就够了。

但是,高并发的情况,就有可能篡改数据。哪怕已经先查后改,还是会出现篡改数据的问题。这个就是两个事务,会出现篡改数据的情况。

所以,怎么解决?加锁。分布式系统,就加分布式锁,比如redis分布式锁。

小结

所以,最终的方案就是,一锁二查三改。

一锁二查三改的代码写在哪里?交易服务。

重复支付

重复支付是多次支付,就是本来买100块钱的东西,结果你支付了两次。

多次支付的具体场景是这样,第一次扫码,然后进入输入金额页面,第二次再提交支付。第二次请求才是真正支付,说白了,就是支付的时候,不小心多次点击提交支付按钮。

一般情况下,前端会按钮置灰,并且还需要输入支付密码,所以其实实际上是很少发生多次支付的。

但是为了以防万一,还是得需要在后端控制一下,怎么控制?基于token机制。具体流程是,第一次扫码,后端写token/订单(包含订单id字段)到redis缓存,并且会返回给前端页面,第二次请求即提交支付的时候,token会再次带到后端来,然后从缓存取,所以哪怕多次提交,最终获取的还是同一笔订单,这里的话就把多次支付的问题给控制住了。

再结合前面讲的同一笔订单,如果出现幂等问题,那么就是用一锁二查三改这套方案来解决。

token/订单的代码写在哪里?网关入口。

所以,核心流程是:扫码——》网关入口:解决重复支付问题——》交易服务:解决幂等问题。

说白了,就是二者结合,才最终解决幂等问题和重复支付这两个不同的问题。