Redisson分布式锁源码-可重入锁的八大机制-上(3)

分布式锁 Redisson 源码剖析

先从Redis可重入锁最简单的Demo入手,一步一图分析Redis可重入锁底层的源码,在边看源码的过程中、边画出Redis可重入锁的
核心流程图。
通过这张核心的流程图,我们可以看到一个企业级的、基于Redis分布式锁的方案是怎样的形成的,在开始分享前,
 大家先思考下如下常见的面试题:
 1、客户端线程在底层是如何实现加锁的?
 2、客户端线程是如何维持加锁的?

分布式锁完整流程图

在这里插入图片描述

加锁成功后如何维持加锁

当我们成功加锁后,我们看到脚本这里返回的是nil,如下图所示:

在这里插入图片描述

此时加锁成功之后,tryLockInnerAsync方法就返回了,所以下一步当然就要再看下调用tryLockInnerAsync方法的位置在干些什么,如下图所示:

在这里插入图片描述

我们会发现当加锁成功之后,这里就会对返回结果ttlRemainingFuture添加一个监听器FutureListener,而监听的核心逻辑当然就在operationComplete方法中,我们可以仔细看下operationComplete方法中在干些什么

因为我们已经加锁成功了,所以第一个if (!future.isSucess())肯定不成立。

根据上文我们已经知道,加锁成功后返回的是nil,这是lua脚本的返回形式,体现到java代码中当然就是得到null,所以if (ttlRemaining == null)毫无疑问成立了,那就再进入scheduleExpirationRenewal方法看下:

在这里插入图片描述

我们看到在方法scheduleExpirationRenewal中创建了一个定时任务task,还记得参数internalLockLeaseTime吗,上文中我们为了看lua脚本代码找到发现是301000ms,此时就可以判定这个定时任务的执行周期是每隔301000/3=10*1000ms,也就是每隔10s执行一次。

那这个定时任务到底在干什么呢?为什么获取锁成功要开启一个定时任务呢?我们继续看:

在这里插入图片描述

定时任务中的这个方法里面,也是一段lua脚本,幸运的是这段脚本比较小段。

首先第一个if中:

redis.call(‘hexists’, KEYS[1], ARGV[2]) == 1,即:hexists anyLock UUID:ThreadId

表示判断当前key中,是否还被线程UUID:ThreadId持有锁,因为是刚刚加锁完毕当然是持有啊,此时就会对这个key进行续期30s。

原来如此,我们好像又解开一个谜团了:

如何维持加锁,原来每次来加锁成功后,监听加锁结果的监听器就会马上开启一个后台线程,每隔10s检查一下key是否存在,如果存在就为key续期30s。

所以一个key往往当过期时间慢慢消逝到20s左右时就又会被定时任务重置为了30s,这样就能保证、只要这个定时任务还在、只要这个key还在,就能让这个key一直存活下去,也就是一直维持加锁。

这个定时任务的机制在Redisson中也被称为watchdog看门狗机制,毕竟还记得超时时间获取吗,参数命名为lockWatchdogTimeout 为30s,如下图所示。

在这里插入图片描述

watchdog看门狗这个机制的命名还挺形象的,好吧,现在我们算是已经知道了客户端是如何维持加锁的了,就是通过一个后台定时任务、每隔10s定时检查key如果存在,就为它自动续期30s。

此时整体流程进度如下图所示:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值