Redisson是如何解决死锁问题的?

普通利用Redis实现分布式锁的时候,我们可能会为某个锁指定某个key,当线程获取锁并执行完业务逻辑代码的时候,将该锁对应的key删除掉来释放锁。

lock->set(key),成功->执行业务,业务执行完毕->unlock->del(key)。

根据这种操作和实践方式,我们可以分为下面两个场景:

1)业务机器宕机

因为我们的业务不知道要执行多久才能结束,所以这个key我们一般不会设置过期时间。这样如果在执行业务的过程中,业务机器宕机,unlock操作不会执行,所以这个锁不会被释放,其他机器拿不到锁,从而形成了死锁。

Redisson为了解决这种情况,设定了一个叫做lockWatchdogTimeout的参数,默认为30秒钟。这样当业务方调用加锁操作的时候,

默认的leaseTime是-1,此时看门狗才会生效,不会走if分支,如果leaseTime被人为设置了值,且不是-1,看门狗不会work。这里会取watch dog的时间作为锁的持有时间,默认是30s,这个时候即使发生了宕机现象,因为这个锁不是永不过期的(宕机之后不不会再续租),所以30s后就会释放,不会产生死锁。

另一方面,它还能解决当锁内逻辑超过30s的时候锁会失效的问题,因为当leaseTime是-1的时候,会启动一个定时任务,在业务方释放锁之前,会一直不停的增加这个锁的生命周期时间,保证在业务执行完毕之前,这个锁一直不会因为redis的超时而被释放(具体参考:汪~汪~汪~redisson的WatchDog是如何看家护院的?_黑少的技术盒子-CSDN博客)。

2)Redis宕机

如果Redis宕机,三种情况:

①Redis是单点模式

②Redis是集群模式,master在获取到一把锁之后(写操作成功后),在没来得及把该锁同步到slave之前就宕掉,这个时候slave没有锁,这把锁失效了……

③Redis是集群模式,而整个集群都宕机,那么就没救了……

Redisson的官方文档里有这段描述(参考:8. Distributed locks and synchronizers · redisson/redisson Wiki · GitHub

“If Redisson instance which acquired lock crashes then such lock could hang forever in acquired state. To avoid this Redisson maintains lock watchdog, it prolongs lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.”

这里说的是拥有Redisson的服务(业务服务)宕机造成的影响吗?如果是,那么和上面说的1)是一个意思。

这里GitHub中文译文翻译可能会引起歧义,8. 分布式锁和同步器 · redisson/redisson Wiki · GitHub

里面翻译的是:

“大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。”

这里说“负责储存这个分布式锁的Redisson节点宕机”可能会引起歧义,Redisson应该指的是客户端,而不是Redis服务实例吧。

如果是要形容Redis有问题而业务系统没问题,应该描述为“如果存储该锁的Redis节点宕机,那么这个锁可能会被无限hang住”。

但是这里为什么会无限hang住,还是要看解锁的部分是如何操作的,后面也会详细说明。(这里貌似是因为Redis的订阅功能,只有当这个锁释放的时候,才会触发所有订阅该锁的其他线程,否则其他线程永远都获取不到锁[如果没有调用带有超时时间获取锁的方法的话],从而造成死锁。这个后面再详细说,这里说的只是猜测,可能并不准确)。

反之,如果不hang住,锁因为Redis节点宕掉而失效,那么其他的线程可以获取锁,但是当前的业务系统还在处理业务,并没有处理完,这里就会有线程安全问题了。

参考:

汪~汪~汪~redisson的WatchDog是如何看家护院的?_黑少的技术盒子-CSDN博客

8. Distributed locks and synchronizers · redisson/redisson Wiki · GitHub

相关文档连接:

Redis官方文档中文链:《Redis官方文档》用Redis构建分布式锁 | 并发编程网 – ifeve.com

Redisson Github中文链接:目录 · redisson/redisson Wiki · GitHub

Redisson Github文档:Home · redisson/redisson Wiki · GitHub

Redisson 官方文档:Redisson: Redis Java client with features of In-Memory Data Grid

其他链接:扒开Redisson的小棉袄,Debug深入剖析分布式锁之可重入锁No.1_黑少的技术盒子-CSDN博客redisson应用之分布式对象 | KL博客

掘金

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐