当前位置: 首页 > news >正文

分布式锁-redisson锁重试和WatchDog机制

抢锁过程中,获得当前线程,通过tryAcquire进行抢锁,该抢锁逻辑和之前逻辑相同。

1、先判断当前这把锁是否存在,如果不存在,插入一把锁,返回null

2、判断当前这把锁是否是属于当前线程,如果是,则返回null

所以如果返回是null,则代表着当前这哥们已经抢锁完毕,或者可重入完毕,但是如果以上两个条件都不满足,则进入到第三个条件,返回的是锁的失效时间,同学们可以自行往下翻一点点,你能发现有个while( true) 再次进行tryAcquire进行抢锁。

long threadId = Thread.currentThread().getId();
Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {return;
}

接下来会有一个条件分支,因为lock方法有重载方法,一个是带参数,一个是不带参数,如果带带参数传入的值是-1,如果传入参数,则leaseTime是他本身,所以如果传入了参数,此时leaseTime != -1 则会进去抢锁,抢锁的逻辑就是之前说的那三个逻辑:

if (leaseTime != -1) {return tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
}

如果是没有传入时间,则此时也会进行抢锁, 而且抢锁时间是默认看门狗时间 commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout()

ttlRemainingFuture.onComplete((ttlRemaining, e) 这句话相当于对以上抢锁进行了监听,也就是说当上边抢锁完毕后,此方法会被调用,具体调用的逻辑就是去后台开启一个线程,进行续约逻辑,也就是看门狗线程:

RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(waitTime,commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(),TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
ttlRemainingFuture.onComplete((ttlRemaining, e) -> {if (e != null) {return;}// lock acquiredif (ttlRemaining == null) {scheduleExpirationRenewal(threadId);}
});
return ttlRemainingFuture;

此逻辑就是续约逻辑,注意看commandExecutor.getConnectionManager().newTimeout() 此方法

Method( new TimerTask() {},参数2 ,参数3 )

指的是:通过参数2,参数3 去描述什么时候去做参数1的事情,现在的情况是:10s之后去做参数一的事情

因为锁的失效时间是30s,当10s之后,此时这个timeTask 就触发了,他就去进行续约,把当前这把锁续约成30s,如果操作成功,那么此时就会递归调用自己,再重新设置一个timeTask(),于是再过10s后又再设置一个timerTask,完成不停的续约

那么大家可以想一想,假设我们的线程出现了宕机他还会续约吗?当然不会,因为没有人再去调用renewExpiration这个方法,所以等到时间之后自然就释放了。

private void renewExpiration() {ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ee == null) {return;}Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws Exception {ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ent == null) {return;}Long threadId = ent.getFirstThreadId();if (threadId == null) {return;}RFuture<Boolean> future = renewExpirationAsync(threadId);future.onComplete((res, e) -> {if (e != null) {log.error("Can't update lock " + getName() + " expiration", e);return;}if (res) {// reschedule itselfrenewExpiration();}});}}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);ee.setTimeout(task);
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • LabVIEW多线圈电磁式振动发电机测试
  • Python3 第三十九课 -- 实例八
  • 对于相同网段的IP,部分无法ping通问题
  • 测试管理工具、自动化测试工具、跨浏览器测试工具 推荐
  • ES中聚合查询之date_histogram查询出现key_as_string 和 key含义
  • 从零开始创建vue3项目——包含项目初始化、element-plus、eslint、axios、router、pinia、echarts
  • 爬虫学习1:初学者简单了解爬虫的基本认识和操作(详细参考图片)
  • php_webshell免杀--从0改造你的AntSword
  • MySQL补充性文件
  • recursion depth exceeded” error
  • 【Linux常用命令】之sed命令
  • 设计模式在FileBrowser中的几个应用
  • CTF-Web习题:2019强网杯 UPLOAD
  • 1.2.2、练习题之十进制转二进制
  • MFC:以消息为基础的事件驱动系统和消息映射机制
  • php的引用
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 4. 路由到控制器 - Laravel从零开始教程
  • C# 免费离线人脸识别 2.0 Demo
  • CSS中外联样式表代表的含义
  • js作用域和this的理解
  • Material Design
  • mysql_config not found
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • vue-cli3搭建项目
  • windows下如何用phpstorm同步测试服务器
  • 聚簇索引和非聚簇索引
  • 排序算法之--选择排序
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 深度学习在携程攻略社区的应用
  • 深入浅出webpack学习(1)--核心概念
  • 为什么要用IPython/Jupyter?
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 中文输入法与React文本输入框的问题与解决方案
  • 白色的风信子
  • ​虚拟化系列介绍(十)
  • #单片机(TB6600驱动42步进电机)
  • (arch)linux 转换文件编码格式
  • (SpringBoot)第二章:Spring创建和使用
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (一)WLAN定义和基本架构转
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .NET 8 跨平台高性能边缘采集网关
  • .net Application的目录
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .net web项目 调用webService
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET+WPF 桌面快速启动工具 GeekDesk
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • ??在JSP中,java和JavaScript如何交互?