支付中常见幂等设计

交易系统中的幂等设计

在一个典型的订单交易系统中,防重和幂等设计是重要而又非常基本的概念。

1.幂等含义:

只要调用接口成功,外部对接口的多次调用得到的结果是相同的。即执行多次和一次的效果是一样的。

2.常见的幂等实现方案:

**1.**最简单的,需要通过唯一的业务单号来保证幂等。也就是说相同的业务单号,认为是同一笔业务。使用这个唯一

的业务单号来确保,后面多次的相同的业务单号的处理逻辑和执行效果是一致的。以支付为例,在不考虑并发的情

况下,实现幂等很简单:①先查询一下订单是否已经支付过,②如果已经支付过,则返回支付成功;如果没有支

付,进行支付流程,修改订单状态为‘已支付’。

缺点:

上述的保证幂等方案是分成两步的,第②步依赖第①步的查询结果,无法保证原子性的。在高并发下就会出现下面

的情况:第二次请求在第一次请求第②步订单状态还没有修改为‘已支付状态’的情况下到来。既然得出了这个结

论,余下的问题也就变得简单:把查询和变更状态操作加锁,将并行操作改为串行操作。

**2 .**在某些场景,想提供无锁的高并发幂等,那么你可以选择为业务单号加上唯一的索引或者组合索引,在并发的

场景中,只有第一笔插入的交易请求能够成功,后续的请求哪怕是慢1ms或者更短时间,都会触发数据库的唯一索

引异常而失败,那么你可以捕获这个异常。

**3.**又或者想把幂等放在服务的最前端,减少实际服务处理的资源浪费,在请求一到达时就提前去重,不让它有执行

的机会,那么可以考虑引入一个redis或类似的组件,将业务请求单号缓存在这个分布式锁的组件内。那么,每当

订单发起交易请求,交易系统会去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为

订单号。查询订单是否已经执行,如果没有则转发到交易系统,执行完成后删除该订单号的Key。当然,Redis是

提供分布式节点下的原子事务操作的。

这是几种常见的幂等方案!

 
comments powered by Disqus [项目] [总结]