Redisson分布式锁使用采坑记

先说问题:
RedissonMultiLock分布式锁在使用的时候,可以指定两个值:等待时间和超时时间

系统中出现的问题:在上游系统调用创建订单的接口时候,网络的原因,导致接口响应超时,上游就进行了自动重试,结果:我这边的系统根据上游的单号生成了两笔同时生效的订单

在前面笔记中redis分布式锁和AOP使用注意问题有说过,接口是做了幂等的校验。并且分布式锁的优先级也低于事务,那这个问题就奇怪了

后来根据线上日志,分析了下,事务和分布式锁优先级也是正常的,和系统接口处理时间超过了redisson的加锁时间导致的;
在redisson锁在加锁的时候,我默认指定了超时时间,但是接口在调用的时候,由于网络的原因,导致我这边的系统去调用下游系统的时候超时了,所以redisson锁就自动释放了,顺带着解决这个问题,也看了下redisson的部分源码,下篇笔记中记录源码

我自己系统中设置的redisson加锁时间是5S,超过5S之后,redisson就自动释放锁了,所以在响应超时的时候,就会出现问题:

  1. A系统调用我的B系统,我们认为是thread1来创建订单,我的B系统在创建订单的时候,也要去调用其他系统获取一些数据进行校验,由于网络的原因,导致我这里响应的时间超过了5S;
  2. 所以此时问题就来了:我加的分布式锁在5S之后,就锁释放了,但是此时thread1的代码还在执行,事务并没有提交
  3. 此时A系统又发起了重试,此时我们认为是thread2来加锁,此时的状况是:上一次加的锁已经释放了,但是事务还没有提交
  4. A系统的thread2尝试加锁,加锁成功了,接着进行了幂等校验,由于此时上一次thread1的事务没有提交,所以数据库中还没有记录,所以幂等校验通过,此时第二次加锁的线程就开始创建订单,在创建的过程中,第一次加锁的线程提交了事务。。。

所以尴尬的是,数据库中对应的表字段也没有加唯一性索引,所以就插入了多条同时生效的记录

解决办法:
1.在数据库中加字段,根据业务单号 + 订单状态 做唯一性索引
2.在redisson加锁的时候,不指定超时时间,让redisson自动续锁
3.将redisson加锁时间设置的更长一点

第三种方法是比较快的一种临时解决方案,但是长远来看,可能还是第一种和第二种会比较好一点

猜你喜欢

转载自blog.csdn.net/CPLASF_/article/details/112002401