redisson分布式锁怎么不自动续锁了?
这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
前言
实际应用中,我们往往一些逻辑在同一时刻只会被调用一次,为了防止多次插入导致重复数据的产生。这种并发问题,我们往往第一时间想到的是java的synchronized、lock来解决,但是这前提条件是在同一个jvm下,那在分布式集群场景下改怎么解决呢?
分布式锁
顾名思义就是在分布式场景下使用锁,简单来说就是由一个第三方来管理锁(redis),分布式服务的各个节点从redis上获得锁,谁拿到锁,谁处理。
RedissonLock
续锁
当设置的分布式锁有效时间小于业务执行时间(业务执行时间不好预知),锁将提前释放,导致业务逻辑重复执行。如果将有效期设置为永久则服务异常宕机、重启等情况没有执行释放锁逻辑,就会导致锁一直无法释放,从而影响后续业务。RedissonLock实现了可以在业务执行没有完成的时候,自动重置锁的有效期。来解决以上两个问题。
RedissonLock的续锁逻辑是用netty下的Timeout定时器来实现的,默认锁时间是30秒,定时器每锁时间/3也就是10秒执行一次。来判断是否还持有锁,如果还持有锁就重置锁时间为30秒。从而避免业务执行时间大于锁时间而导致的锁被释放了的问题。
源码:
但当我们这样使用锁的时候,就会发现无法自动续锁
boolean isLock = lock.tryLock(6, 6, TimeUnit.SECONDS);
第一个参数6代表锁的有效期是6,第二个参数6代表阻塞等待获取所的超时时间是6,第三个参数是时间单位。
理论上按照续锁的规则,应该每2秒会去判断是否还持有锁,可是为什么没执行呢?问题出在了这一行代码上
这里有个判断逻辑,如果自定义了锁的有效期则会只执行tryLockInnerAsync方法,而不会去执行续锁方法scheduleExpirationRenewal。
总结
当我们需要用到续锁功能时,一要记住不要设置锁的过期时间,可以设置成-1.一旦设了时间,RedissonLock就会认为你需要自己控制锁时间,而放弃执行续锁逻辑。 查看源码,不难发现续锁逻辑开销挺大的,需要起定时器。所以要注意这点,并不是所有分布式场景都需要续锁逻辑的。当我们很难判断业务逻辑的执行时间时,不妨开启续锁。
转载自:https://juejin.cn/post/7026291454532124680