如何确保分布式场景下的并发锁幂等

                  如何确保分布式场景下的并发锁幂等

目录

1、数据库的唯一索引

2、分布式锁



1、数据库的唯一索引


例如:退款服务 和支付服务
出账流水记录表通过设置退款编码字段,判断是否存在这笔退款的已支付的出账流水记录。
存在即返回,不存在即插入,进入接下来的处理流程。
缺点:当遇到分库分表的方案时,需要先查询数据库,判断约束资源字段是否重复,不存在再执行插入操作。(先执行select,再执行insert,当遇到高并发时,可能会出现并发安全问题,造成重复的数据写入)


2、分布式锁

获取锁令牌,对约束的资源进行写操作

Redis
setnx 命令:给定的key不存在,进行插入;已经存在时,不需要做任何动作。
为了防止死锁,需要进行设置一个过期时间,进行自动锁的销毁。
原因:假设一个支付集群,退款服务发起了5个重复的退款请求,并且他们具有相同的退款编号,其中第一次请求它操作成功,它获取到了分布式锁,存活时间为10分钟。然后由于网络不稳定或者服务限流了,导致调用大量接口失败了。这时,我们一般会采用消息队列进行失败重试,这个任务在队列中不断的排队与重试,如果这个过程十分耗时,超过30分钟才成功了。这时分布式锁已经失效了。换句话说,队列中剩下的退款请求就会正常调用退款请求(分布式锁失效了),造成资金受损。
所以,我们需要确保分布式锁的失效时间不能小于业务的最大重试时间,以此保证业务层面的合法性。
分布式锁只是保存资源的一致性,还需要通过幂等机制保证数据的一致性。
1、可以采取分布式锁 + 数据持久化 的方法,针对我们设置的约束资源字段做第二次的校验
2、引入状态机,通过状态机进行状态约束和状态流转,状态机确保同一个业务是流程化执行

void pay() {
 if(order.status == '待支付') {

     // TODO处理逻辑

}



总结:

 

猜你喜欢

转载自blog.csdn.net/xiao__jia__jia/article/details/105618323