Redisson分布式锁,重试锁和锁续命的原理

RedissonLock 锁重试原理

tryLock有三个三个参数,第一个是等待时间,第二个是锁失效后自动释放的时间,不填默认为-1,第三个是时间单位;
当设置了第一个参数,那这个锁就成了可重试锁;获取锁失败后,就不会立即返回了;会在等待内不断重试;如果在等待时间结束后,还没有获取到锁,那就失败了。
获取当前时间,线程ID,尝试获取锁,判断锁失效后自动释放的时间是否等于-1,如果不等于,就用自己的锁释放时间,如果等于-1,异步调用tryLockInnerAsync,返回值是个Future,第一个参数是等待时间,第二个参数是锁释放时间,看门狗的默认30秒,第三个是时间单位,第四个参数是线程ID,这个方法内是个lua脚本,成功返回空,是否返回过期时间;判断返回值是否为空,不为空,计算剩余等待时间,判断等待时间>0,大于就去尝试获取锁,但不是立即获取锁,是在剩余等待时间内订阅了锁释放的情况(锁释放的时候会发布通知),返回值也是个Future,如果超时了,会取消订阅;如果锁已经释放了,计算剩余等待时间,判断剩余等待时间>0,开始循环,就可以重新获取锁,和上面一样,如果失败,同时上,但这里用的是信号量。

在这里插入图片描述
lock.tryLock方法

第一个参数(等待时间),如果设置了,获取锁失败后,就不会立即返回了;会在等待内不断重试;如果在等待时间结束后,还没有获取到锁,那就失败了。所以设置后就变成了可重试的锁了。
第二个参数(锁失效后自动释放的时间,不填默认为-1)
第三个参数(时间单位)
源码跟进

在这里插入图片描述

第二个参数没给,默认值-1,跟进去tryLock方法看看

在这里插入图片描述

在这里插入图片描述
跟进tryAcquire方法,尝试获取锁
在这里插入图片描述
跟进tryAcquireAsync方法

//源码private <T> RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {	//判断释放锁的时间是否为-1if (leaseTime != -1L) {//用自己的释放锁的时间return this.tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);} else {//如果是-1,设置一个默认的释放锁的时间,30秒(getLockWatchdogTimeout)RFuture<Long> ttlRemainingFuture = this.tryLockInnerAsync(waitTime, this.commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(), TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);ttlRemainingFuture.onComplete((ttlRemaining, e) -> {if (e == null) {if (ttlRemaining == null) {this.scheduleExpirationRenewal(threadId);}}});return ttlRemainingFuture;}}

在这里插入图片描述
跟进getLockWatchdogTimeout看门狗

显示默认30秒
在这里插入图片描述
返回RedissonLock类,继续跟进tryLockInnerAsync方法

tryLockInnerAsync 异步方法,有没有拿到结果不清楚

在这里插入图片描述

看到有lua脚本

lua脚本
判断锁是否存在
不存在设置锁标识,v+1
设置有效期
存在,判断锁是不是我自己的
是,v+1
设置有效期
成功获取锁,返回空
失败,返回锁的有效期(毫秒)

  <T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {//释放锁的时间,记录到本地一个成员变量里this.internalLockLeaseTime = unit.toMillis(leaseTime);return this.evalWriteAsync(this.getName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hincrby', KEYS[1], ARGV[2], 1);redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1)then redis.call('hincrby', KEYS[1], ARGV[2], 1);redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end;return redis.call('pttl', KEYS[1]);", Collections.singletonList(this.getName()), this.internalLockLeaseTime, this.getLockName(threadId));}

一步一步往上返回,返回到RedissonLock类中的tryLock方法的tryAcquire方法,结果有两种,一种是获取锁成功返回值为空,另一种是获取锁失败返回值为锁释放的时间

在这里插入图片描述
继续

在这里插入图片描述

锁续命

当用默认的锁释放时间时,且已经拿到锁,会创建一个 ConcurrentMap来存锁的记录,以锁的名称为k,线程id为V,判断是否第一次来,如果是开启一个延时任务,10秒后执行,执行的就是更新有效期的lua脚本,更新成功后,开始递归,无限续约。

先看锁释放时间是默认值-1的情况
在这里插入图片描述
跟进 scheduleExpirationRenewal 方法
在这里插入图片描述
跟进 renewExpiration 方法
在这里插入图片描述
跟进 renewExpirationAsync 方法

判断锁是不是当前线程拿到的,是就重置有效期

   protected RFuture<Boolean> renewExpirationAsync(long threadId) {return this.evalWriteAsync(this.getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1)then redis.call('pexpire', KEYS[1], ARGV[1]); return 1; end; return 0;",Collections.singletonList(this.getName()), this.internalLockLeaseTime, this.getLockName(threadId));}

执行lua脚本后
在这里插入图片描述

释放锁

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/5666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++的演变与未来:编程艺术的持续进化

在计算机编程的演变历程中&#xff0c;C以其独特的魅力和强大的功能&#xff0c;一直占据着不可或缺的地位。从最初的面向对象编程&#xff0c;到如今的跨平台、高性能应用&#xff0c;C在不断地适应和推动着计算机技术的发展。本文将深入剖析C的演变过程&#xff0c;展望其未来…

【全国青少年信息素养大赛智能算法挑战赛初中模拟卷】

目录 模拟卷1 全国青少年信息素养大赛智能算法挑战赛初中模拟卷2 全国青少年信息素养大赛智能算法挑战赛初中模拟卷3 模拟卷1 单选题&#xff08;每题 5 分&#xff0c;共 75 分&#xff09; 1. 在C中&#xff0c;哪个关键字用于指定一个类为另一个类的基类&#xff1f; - A…

C++ 优先级队列priority_queue

1、常用接口 底层使用的是堆实现&#xff0c;默认为大堆 2、理解&#xff1a; 优先级队列就是即使插入的是一个乱序的&#xff0c;但是依旧会按照有序的顺序出队列 优先级队列就是会根据大小来出队列&#xff0c;而不是谁在队头就出谁。 优先级队列底层是使用堆实现&#x…

Java项目:基于SSM框架实现的实践项目管理系统(ssm+B/S架构+源码+数据库+毕业论文+开题报告)

一、项目简介 本项目是一套基于SSM框架实现的实践项目管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff…

SpringBoot @MockBean 导致ApplicationContext Reload带来的问题的解决方法

在基于SpringBoot的项目中&#xff0c;编写单元测试时&#xff0c;会遇到需要对一些被Spring容器管理的对象进行Mock的处理&#xff0c;但是这些对象可能被引用的比较多。这个时候可以使用 MockBean 来注释相关对象。 如下面的代码片段&#xff1a; package com.example.spri…

【前端】-【防止接口重复请求】

文章目录 需求实现方案方案一方案二方案三 需求 对整个的项目都做一下接口防止重复请求的处理 实现方案 方案一 思路&#xff1a;通过使用axios拦截器&#xff0c;在请求拦截器中开启全屏Loading&#xff0c;然后在响应拦截器中将Loading关闭。 代码&#xff1a; 问题&…

CentOS-Stream-9配置vsftpd

步骤一 vim /etc/vsftpd/vsftpd.conf&#xff0c;anonymous_enableYES&#xff0c;允许匿名。 systemctl enable vsftpd 设置vsftpd开机自动启动 systemctl restart vsftpd 重启vsftpd systemctl stop firewalld 关闭防火墙&#xff0c;匿名访问ftp成功&#xff0c;普通用户…

【MySQL】驱动表、被驱动表详解。—— 性能优化。

文章目录 什么是 驱动表 和 被驱动表&#xff1f;哪个表是驱动表&#xff1f;性能优化建议&#xff1a; 我是一名立志把细节都说清楚的博主&#xff0c;欢迎【关注】&#x1f389; ~ 原创不易&#xff0c; 如果有帮助 &#xff0c;记得【点赞】【收藏】 哦~ ❥(^_-)~ 如有错误…

Coursera: An Introduction to American Law 学习笔记 Week 04: Constitutional Law

An Introduction to American Law 本文是 https://www.coursera.org/programs/career-training-for-nevadans-k7yhc/learn/american-law 这门课的学习笔记。 文章目录 An Introduction to American LawInstructors Week 04: Constitutional LawKey Constitutional Law TermsSup…

nginx connect 异常

1.nginx反向代理 # 测试server {listen 80;server_name local.dongpeng.com;location / {# proxy_pass http://192.168.10.131:9394;proxy_pass http://127.0.0.1:9394;}} 2.出现异常 2024/05/01 17:53:41 [error] 6#6: *1 connect() failed (111: Connection refused…

pytorch多卡分布式训练卡住的问题

最近需要模型进行多任务学习&#xff0c;完成代码后单卡跑是没有问题的。但是多卡跑基本上会出现卡在第一个迭代的情况。忙了一天总算是解决了。总结一下我这里的原因&#xff1a; 我的代码里执行了torch.distributed.all_reduce() 的操作&#xff0c;但这个操作只服务于一个ta…

华纳云:ubuntu中fdisk找不到硬盘怎么解决?

如果在 Ubuntu 中使用 fdisk 命令找不到硬盘&#xff0c;可能是由于以下几个原因导致的&#xff1a; 1.未正确识别硬盘&#xff1a;可能是因为硬盘未被正确识别或未被操作系统识别。这可能是由于硬件连接问题、硬盘故障、驱动问题等引起的。 2.需要管理员权限&#xff1a;在 Ub…

黑马 - websocket搭建在线聊天室

这里写自定义目录标题 一、消息推送常见方式二、websocket 是什么&#xff1f;三、websocket api的介绍1、客户端 &#xff08;浏览器&#xff09; 四、实现在线聊天室1、需求2、聊天室流程分析3、消息格式4、代码实现 一、消息推送常见方式 1、轮训方式 2、SSE&#xff08;…

EasyDarwin录像存储

目录 1、安装ffmpeg 2、建立录像存储路径 3、修改EasyDarwin配置文件 4、测试 (1)推流&#x

2024年第二十一届 五一杯 (A题)大学生数学建模挑战赛 | 多目标优化问题,深度学习分析 | 数学建模完整代码解析

DeepVisionary 每日深度学习前沿科技推送&顶会论文&数学建模与科技信息前沿资讯分享&#xff0c;与你一起了解前沿科技知识&#xff01; 本次DeepVisionary带来的是五一杯的详细解读&#xff1a; 完整内容可以在文章末尾全文免费领取&阅读&#xff01; 第一个问题…

【Linux】进程终止

思维导图 学习内容 进程终止是进程控制里面的一个重要的知识&#xff0c;通过这一篇博客&#xff0c;我们可以学习到进程终止的概念&#xff0c;进程终止的三种情况&#xff0c;进程终止的退出码和退出信号&#xff0c;最后在来学习进程是如何进行终止的。 学习目标 进程终止…

诺基亚贝尔探访上海斯歌,共探创新合作新机遇

近日&#xff0c;上海斯歌K2 BPM迎来重要客户考察交流活动。来自诺基亚贝尔的首席数字官刘少勇一行莅临了上海斯歌K2 BPM 的武汉研发中心&#xff0c;并对上海斯歌在BPM业务流程管理领域的研发成果及交付能力给予了高度肯定。 此次活动不仅加深了双方的战略合作&#xff0c;也为…

维修家政按摩到家上门小程序开源版开发

维修家政按摩到家上门小程序开源版开发 智能定位&#xff0c;精准计费——全新上门服务平台功能解析。 全新上门服务平台已经上线&#xff0c;它拥有一系列强大的功能&#xff0c;旨在为用户提供最便捷、最个性化的服务体验。 !](https://img-blog.csdnimg.cn/direct/86195e…

Linux 查看主机内存,CPU使用率的两种推荐指令top ,free 指令解读

top 指令 top 指令是 Linux 系统中一个实时显示系统状态的动态视图工具&#xff0c;主要用于监控系统的整体运行状态&#xff0c;包括CPU使用率、内存使用情况、运行中的进程信息等。它是一个非常强大的命令行工具&#xff0c;常用于性能分析和故障排查。下面是一些基本的使用…

【QEMU系统分析之实例篇(八)】

系列文章目录 第八章 QEMU系统仿真的机器创建分析实例 文章目录 系列文章目录第八章 QEMU系统仿真的机器创建分析实例 前言一、QEMU是什么&#xff1f;二、QEMU系统仿真的机器创建分析实例1.系统仿真的命令行参数2.目标机器创建过程3.输出分析 总结 前言 本文以 QEMU 8.2.2 为…