交易系统中的幂等设计
在一个典型的订单交易系统中,防重和幂等设计是重要而又非常基本的概念。
1.幂等含义:
只要调用接口成功,外部对接口的多次调用得到的结果是相同的。即执行多次和一次的效果是一样的。
2.常见的幂等实现方案:
**1.**最简单的,需要通过唯一的业务单号来保证幂等。也就是说相同的业务单号,认为是同一笔业务。使用这个唯一
的业务单号来确保,后面多次的相同的业务单号的处理逻辑和执行效果是一致的。以支付为例,在不考虑并发的情
况下,实现幂等很简单:①先查询一下订单是否已经支付过,②如果已经支付过,则返回支付成功;如果没有支
付,进行支付流程,修改订单状态为‘已支付’。
缺点:
上述的保证幂等方案是分成两步的,第②步依赖第①步的查询结果,无法保证原子性的。在高并发下就会出现下面
的情况:第二次请求在第一次请求第②步订单状态还没有修改为‘已支付状态’的情况下到来。既然得出了这个结
论,余下的问题也就变得简单:把查询和变更状态操作加锁,将并行操作改为串行操作。
**2 .**在某些场景,想提供无锁的高并发幂等,那么你可以选择为业务单号加上唯一的索引或者组合索引,在并发的
场景中,只有第一笔插入的交易请求能够成功,后续的请求哪怕是慢1ms或者更短时间,都会触发数据库的唯一索
引异常而失败,那么你可以捕获这个异常。
**3.**又或者想把幂等放在服务的最前端,减少实际服务处理的资源浪费,在请求一到达时就提前去重,不让它有执行
的机会,那么可以考虑引入一个redis或类似的组件,将业务请求单号缓存在这个分布式锁的组件内。那么,每当
订单发起交易请求,交易系统会去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为
订单号。查询订单是否已经执行,如果没有则转发到交易系统,执行完成后删除该订单号的Key。当然,Redis是
提供分布式节点下的原子事务操作的。
这是几种常见的幂等方案!
comments powered by Disqus [项目] [总结]