关于springboot使用redisTemplate实现分布式锁的问题。
代码如上,通过redisTemplate的api里的setIfAbsent给redis加锁,然后用delete去解锁。在buy方法中先加锁然后阻塞十秒模拟业务流程,业务流程以后再解锁。然后打开浏览器,开俩个窗口,模拟俩个线程去调用buy(俩个线程参数key是一样)。理想中的过程是,第一个线程调用的时候,加锁以后然后阻塞的十秒之内,再用第二个窗口模拟第二个线程去调用,然后setIfAbsent返回false,buy方法直接返回lock来表示本次调用失效。想实现这么一个接口幂等性校验的场景。
但是这个场景没有实现,发现了一个问题,在第一个线程调用setIfAbsent以后,然后再阻塞的10秒之内, 第二个线程再用相同的key去调用setIfAbsent,会一直等待第一个线程完全执行完以后,setIfAbsent才会返回。但是再第一个线程执行完以后,已经将该key进行了delete,所以第二个线程调用setIfAbsent的结果也是true,俩个线程都返回了buy,导致无法实现接口幂等性校验的场景。
个人对redis了解的比较少,以前都是用来存放用户的token用,以我个人的直觉猜测可能是redis的事务问题,在第一个线程执行setIfAbsent后,阻塞的十秒时间内,redis一直是事务未提交的状态,然后第二个线程再接着去调用setIfAbsent发现该key未提交事务,会一直等待第一个事务提交完事务以后,再进行setnx操作。但是这个也只是本人对关系型数据库的了解作出的猜测,对非关系行数据库确实了解了解较少,所有在此希望CSDN各位可以为指教一下出现这个问题的原因和解决方案。