舒服了,踩到一个关于分布式锁的非比寻常的BUG

提到分布式锁,大家一般都会想到 Redis。

想到 Redis,一部分同学会说到 Redisson。

那么说到 Redisson,就不得不掰扯掰扯一下它的“看门狗”机制了。

所以你以为这篇文章我要给你讲“看门狗”吗?

不是,我主要是想给你汇报一下我最近研究的由于引入“看门狗”之后,给 Redisson 带来的两个看起来就菊花一紧的 bug :

  • 看门狗不生效的 BUG。
  • 看门狗导致死锁的 BUG。

为了能让你丝滑入戏,我还是先简单的给你铺垫一下,Redisson 的看门狗到底是个啥东西。

看门狗描述

你去看 Redisson 的 wiki 文档,在锁的这一部分,开篇就提到了一个单词:watchdog

github.com/redisson/re…

watchdog,就是看门狗的意思。

它是干啥用的呢?

好的,如果你回答不上来这个问题。那当你遇到下面这个面试题的时候肯定懵逼。

面试官:请问你用 Redis 做分布式锁的时候,如果指定过期时间到了,把锁给释放了。但是任务还未执行完成,导致任务再次被执行,这种情况你会怎么处理呢?

这个时候,99% 的面试官想得到的回答都是看门狗,或者一种类似于看门狗的机制。

如果你说:这个问题我遇到过,但是我就是把过期时间设置的长一点。

时间到底设置多长,是你一个非常主观的判断,设置的长一点,能一定程度上解决这个问题,但是不能完全解决。

所以,请回去等通知吧。

或者你回答:这个问题我遇到过,我不设置过期时间,由程序调用 unlock 来保证。

好的,程序保证调用 unlock 方法没毛病,这是在程序层面可控、可保证的。但是如果你程序运行的服务器刚好还没来得及执行 unlock 就宕机了呢,这个你不能打包票吧?

这个锁是不是就死锁了?

所以......

为了解决前面提到的过期时间不好设置,以及一不小心死锁的问题,Redisson 内部基于时间轮,针对每一个锁都搞了一个定时任务,这个定时任务,就是看门狗。

在 Redisson 实例被关闭前,这个狗子可以通过定时任务不断的延长锁的有效期。

因为你根本就不需要设置过期时间,这样就从根本上解决了“过期时间不好设置”的问题。默认情况下,看门狗的检查锁的超时时间是 30 秒钟,也可以通过修改参数来另行指定。

如果很不幸,节点宕机了导致没有执行 unlock,那么在默认的配置下最长 30s 的时间后,这个锁就自动释放了。

那么问题来了,面试官紧接着来一个追问:怎么自动释放呢?

这个时候,你只需要来一个战术后仰:程序都没了,你觉得定时任务还在吗?定时任务都不在了,所以也不会存在死锁的问题。

搞 Demo

前面简单介绍了原理,我也还是给你搞个简单的 Demo 跑一把,这样更加的直观。

引入依赖,启动 Redis 什么的就不说了,直接看代码。

示例代码非常简单,就这么一点内容,非常常规的使用方法:

把项目启动起来,触发接口之后,通过工具观察 Redis 里面 whyLock 这个 key 的情况,是这样的:

你可以看到在我的截图里面,是有过期时间的,也就是我打箭头的地方。

然后我给你搞个动图,你仔细看过期时间(TTL)这个地方,有一个从 20s 变回 30s 的过程:

首先,我们的代码里面并没有设置过期时间的动作,也没有去更新过期时间的这个动作。

那么这个东西是怎么回事呢?

很简单,Redisson 帮我们做了这些事情,开箱即用,当个黑盒就完事了。

接下来我就是带你把黑盒变成白盒,然后引出前面提到的两个 bug。

我的测试用例里面用的是 3.16.0 版本的 Redission,我们先找一下它关于设置过期动作的源码。

首先可以看到,我虽然调用的是无参的 lock 方法,但是它其实也只是一层皮而已,里面还是调用了带入参的 lock 方法,只不过给了几个默认值,其中 leaseTime 给的是 -1:

而有参的 lock 的源码是这样的,主要把注意力放到我框起来的这一行代码中:

tryAcquire 方法是它的核心逻辑,那么这个方法是在干啥事儿呢?

点进去看看,这部分源码又是这样的:

其中 tryLockInnerAsync 方法就是执行 Redis 的 Lua 脚本来加锁。

既然是加锁了,过期时间肯定就是在这里设置的,也就是这里的 lea

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值