Redisson分布式锁-锁的可重入、可重试、WatchDog超时续约、multLock联锁(一文全讲透,超详细!!!)

news2025/7/19 12:13:47

本文涉及到使用Redis实现基础分布式锁以及Lua脚本的内容,如有需要可以先参考博主的上一篇文章:Redis实现-优惠卷秒杀(基础版本)
在这里插入图片描述

一、功能介绍

(1)前面分布式锁存在的问题

  1. 在JDK当中就存在一种可重入锁ReentrantLock,可重入指的是在同一线程当中可以多次获取同一把锁;
  2. 之前实现的分布式锁是一种非阻塞式不可重试的锁,而在很多业务中第一时间获取锁失败是可以进行等待再重试的;
  3. 超时释放的逻辑不严谨,不可以简单设定一个超时时间即可;
  4. Redis的主从模式也可以理解为读写分离模式,也就是说Redis会有一个主节点与多个从节点,执行写操作时是访问主节点,执行读操作时访问的是从节点,同时需要主节点同步数据给从节点,保证主从数据一致性,而执行set获取锁操作就是一种写操作,当我们在主节点执行该动作时假如主节点宕机,没有完成数据同步,这时其他线程再从另一个节点上获取锁,可能就会出现线程安全问题。
    在这里插入图片描述

(2)Redisson介绍

"在Redis基础上实现的Java驻内存虚拟网格"意思是:在Redis基础上实现的一个分布式工具集合,也就是在分布式系统下可能用到的各种各样的工具。

在这里插入图片描述

二、可重入锁快速入门

在这里插入图片描述
在这里插入图片描述
tryLock方法是一个阻塞式动作,执行该方法就可以尝试去获取锁,而在设置的最大等待时间内,若发生获取锁失败,就会等待一小段时间并重试,在超过该最大等待时间后都没有拿到锁才会返回false,也就是一种重试机制
(1)代码改造
在这里插入图片描述
在这里插入图片描述

三、可重入锁的实现原理

在使用原来自行实现的分布式锁时,数据类型是String,仅可存放锁名称lock以及线程id的key-value数据值,不能实现可重入功能是因为我们获取锁主要依靠setnx命令,所以即便value中的线程id相同,也不能去重复set
在这里插入图片描述

要想实现可重入就可以参考JDK当中的可重入锁ReentrantLock的实现原理:简单来说就是在首次获取锁是使用setnx命令进行设置,在后续获取锁时若发现锁已存在则使用get命令去判断线程id是否相同,若相同则也可以成功取到,并且同时去记录锁的重入次数

那么现在使用的String类型数据结构就无法满足再去存放锁的重入次数的数据的要求,就可以改用hash类型
这种可重入锁的释放动作不能去直接删除整个数据,而是要去将重入次数减一,当重入次数减至0时就可以删除该锁,也就需要在每次释放锁时都去判断一下锁的重入次数是否为0了。
注意:hash类型的命令与先前String类型的命令不同,也就是不能直接使用setnx ex命令,需要去改变。

(1)完整执行流程

在这里插入图片描述
因为这里流程较为复杂,使用的Redis命令较多,为了保证逻辑的原子性就要使用Lua脚本来编写。

(2)Lua脚本编写

①获取锁

在这里插入图片描述

②释放锁

在这里插入图片描述

四、锁重试和WatchDog机制

在这里插入图片描述

(1)源码分析

①锁重试机制

在使用tryLock方法进行传参时发现同时存在两种实现方式,一种是直接指定超时时间与锁自动释放时间;一种是只指定超时时间
在这里插入图片描述
跟入tryLock内的tryAcquire获取锁方法
在这里插入图片描述
当我们调用tryLock方法时不去指定锁自动释放时间,只指定超时时间,那么在源码中就会自动为leaseTime值赋默认值为-1。
在该方法中首先会去判断leaseTime是否为-1,若不是则会去走默认获取锁的方法tryLockInnerAsync;若是则会借助getLockWatchdogTimeout方法 (WatchDog意为看门狗)来为该锁初始化一个超时时间–30s
在这里插入图片描述
在这里插入图片描述
跟入该tryLockInnerAsync方法,可以看到当获取锁成功时返回的是null,获取失败时返回的是锁的剩余时间ttl
在这里插入图片描述
获取到返回的锁剩余时间ttl后,若ttl不为null,那么就会去计算超时剩余时间,若时间仍有余则可以继续去尝试获取锁。

而在这里使用了subscribe订阅方法,用于订阅其他线程释放锁的信息,在Redis中的publish命令就是用于发布消息通知。

假设在超时剩余时间结束后还没有接收到锁释放通知,就会去取消订阅,并且返回false;
在这里插入图片描述
在这里插入图片描述
相反假设在超时剩余时间前接收到了锁释放通知,且超时剩余时间仍有余,就会再次去执行跟上面类似的重试获取锁的逻辑。在每次执行完这段逻辑后假设还没有获取到锁,但是超时剩余时间仍有余,那么就可以再次循环执行。
在这里插入图片描述

但是这里与上方的差别在于:这里采用的是监听信号量的方案,假设在其他线程中进行了锁释放,那么就会发出一个信号,并且在这边去尝试获取信号。

但是尝试获取信号也会存在一个最大等待时间,如果超过这个时间依然没有拿到锁则会返回false。我们也通过subscribeFuture这个Future对象来实现定时获取,也就是在等待指定时间后再去尝试获取锁,类似阻塞的原理,避免无效尝试,降低CPU消耗
在这里插入图片描述

②锁超时续约

假设我们获取锁成功并得到锁的剩余有效期ttl,但是此时有业务阻塞了,导致ttl到期,其他线程捕捉到这个信号就会立刻再去获取锁,那么就会出现线程安全问题了。也就是说我们必须要确定锁是因为业务执行完释放的,而不是因为阻塞释放
前面我们已经了解到当不直接指定锁超时时间时,会利用WatchDog看门锁机制来为该锁加上一个默认超时时间为30s。那么当获得到这个Future对象后,就会去判断锁的剩余有效期是否为null,若为null则会对锁剩余时间进行续约动作。
在这里插入图片描述
在这里插入图片描述

在该方法中每隔锁内部施放时间的三分之一 (internalLockLeaseTime / 3L,在这里可以理解为看门狗时间的三分之一,也就是30 / 3 = 10s),就会去自动刷新一次有效期。

在这里插入图片描述
也就是重置锁的有效期时间
在这里插入图片描述
因为在在方法该方法中又去递归调用自身,所以实现的是无限续约,也就可以理解为永不过期。
当锁释放时,才会去取消这个锁自动更新任务。
在这里插入图片描述
在这里插入图片描述

(2)总结

在这里插入图片描述

五、multLock

(1)主从一致性问题的产生原因

主从一致性导致的锁失效问题:
Redis的主从模式也可以理解为读写分离模式,也就是说Redis会有一个主节点与多个从节点,执行写操作时是访问主节点,执行读操作时访问的是从节点,同时需要主节点同步数据给从节点,保证主从数据一致性。而执行set获取锁操作就是一种写操作,当我们在主节点获取到锁后假如主节点发生宕机,没有完成数据同步,那么Redis的哨兵机制就会从其他从节点中选出一个新的主节点,但是这时从节点中没有该锁的数据,就相当于发生了锁失效,其他线程再来获取锁也是同样可以获取成功的,也就会出现线程安全问题。

在这里插入图片描述
Redis中解决该问题的思路:打破主从节点的思路,在每个节点上都保存该锁,并且当Java应用想要去获取锁时必须依次向每个节点都去获取锁,必须从每个节点处都能获取到锁、都保存了锁的标识,才算获取锁成功。
而且这种方案还同时保留了主从一致性机制,每个节点都可以去形成自己的主从关系,即便在一个主从节点上发生了不一致,只要其他两个节点上不发生问题那么最后都是可以健康运行的。

这套方案保留了主从一致性机制,确保了整个Redis集群的高可用特性,同时避免了主从一致性引发的锁失效问题。

在这里插入图片描述
所以multLock又称为"联锁"。

(2)代码实现

首先去准备多台Redis节点,并在Java应用中完成配置客户端
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注入三个Redis客户端并获取联锁
在这里插入图片描述
在这里插入图片描述
运行测试,发现在三个节点上都保存了锁
在这里插入图片描述

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

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

相关文章

语言模型:AM-Thinking-v1 能和大参数语言模型媲美的 32B 单卡推理模型

介绍 a-m-team 是北科 (Ke.com) 的一个内部团队,致力于探索 AGI 技术。这是一个专注于增强推理能力的 32B 密集语言模型。 a-m-team / AM-Thinking-v1 是其旗下的一个语言模型,采用低成本的方式能实现和大参数模型媲美。 DeepSe…

ChatGPT:OpenAI Codex—一款基于云的软件工程 AI 代理,赋能 ChatGPT,革新软件开发模式

ChatGPT:OpenAI Codex—一款基于云的软件工程 AI 代理,赋能 ChatGPT,革新软件开发模式 导读:2025年5月16日,OpenAI 发布了 Codex,一个基于云的软件工程 AI 代理,它集成在 ChatGPT 中&#xff0c…

智能视觉检测技术:制造业质量管控的“隐形守护者”

在工业4.0浪潮的推动下,制造业正经历一场以智能化为核心的变革。传统人工质检模式因效率低、误差率高、成本高昂等问题,逐渐难以满足现代生产对高精度、高速度的需求。智能视觉检测技术作为人工智能与机器视觉融合的产物,正成为制造业质量管控…

利用html制作简历网页和求职信息网页

前言 大家好,我是maybe。今天下午初步学习了html的基础知识。做了两个小网页,一个网页是简历网页,一个网页是求职信息填写网页。跟大家分享一波~ 说明:我不打算上传图片。所以如果有朋友按照我的代码运行网页,会出现一个没有图片…

卷积神经网络进阶:转置卷积与棋盘效应详解

【内容摘要】 本文深入解析卷积神经网络中的转置卷积(反卷积)技术,重点阐述标准卷积与转置卷积的计算过程、转置卷积的上采样作用,以及其常见问题——棋盘效应的产生原因与解决方法,为图像分割、超分辨率等任务提供理论…

2025年5月13日第一轮

1.百词斩 2.安全状态和死锁 3.银行家算法和状态图 4.Vue运行 5.英语听力 6.词汇 7.英语 长篇:数学竞赛 8.数学 间断点类型和数量 The rapid development of artificial intelligence has led to widerspareasd concreasns about job displacemant.As AI technology conti…

小结:Android系统架构

https://developer.android.com/topic/architecture?hlzh-cn Android系统的架构,分为四个主要层次:应用程序层、应用框架层、库和运行时层以及Linux内核层。: 1. 应用程序层(Applications) 功能:这一层包…

基于C#的MQTT通信实战:从EMQX搭建到发布订阅全解析

MQTT(Message Queueing Telemetry Transport) 消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点。 它被设计用于低带宽,不稳定或高延迟的…

ISP中拖影问题的处理

有时候会出现如下的阴影问题该如何处理呢?本文将提供几个思路。 1、降低曝光时间 如果曝光时间过大,会统计整个曝光时间内的图像信息,就会导致拖影的产生,这个时候可以考虑降低一下曝光时间。 2、时域降噪过大 只要明白时域降噪…

SQLMesh 模型管理指南:从创建到验证的全流程解析

本文全面介绍SQLMesh这一现代化数据转换工具的核心功能,重点讲解模型创建、编辑、验证和删除的全生命周期管理方法。通过具体示例和最佳实践,帮助数据工程师掌握SQLMesh的高效工作流程,包括增量模型配置、变更影响评估、安全回滚机制等关键操…

HarmonyOS AVPlayer 音频播放器

鸿蒙文档中心:使用AVPlayer播放视频(ArkTS)文档中心https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/video-playback 这张图描述的是 HarmonyOS AVPlayer 音频播放器的状态流转过程,展示了 AVPlayer 在不同状态之间的切换条件和关键操作…

⭐️白嫖的阿里云认证⭐️ 第二弹【课时1:提示词(Prompt)技巧】for 「大模型Clouder认证:利用大模型提升内容生产能力」

「大模型Clouder认证:利用大模型提升内容生产能力」这个认证目前在阿里云认证中心还是免费的,简单几步就可以申请考试,有两次的免费考试机会。而且,这个课程中的内容对于所有普通用户来说都非常实用,课程整体长度也就3节课,非常快速就能学完。心动不如行动,赶紧开始吧!…

Filament引擎(一) ——渲染框架设计

filament是谷歌开源的一个基于物理渲染(PBR)的轻量级、高性能的实时渲染框架,其框架架构设计并不复杂,后端RHI的设计也比较简单。重点其实在于项目中材质、光照模型背后的方程式和理论,以及对它们的实现。相关的信息,可以参考官方…

c++从入门到精通(六)--特殊工具与技术-完结篇

文章目录 特殊工具与技术-完结篇控制内存分配运行时类型识别成员指针嵌套类局部类固有的不可抑制特性位域volatile限定符链接指示 extern "C" 特殊工具与技术-完结篇 控制内存分配 重载new和delete: ​ 如果应用程序希望控制内存分配的过程,…

MCP实战:在扣子空间用扣子工作流MCP,一句话生成儿童故事rap视频

扣子最近迎来重要更新,支持将扣子工作流一键发布成MCP,在扣子空间里使用。 这个功能非常有用,因为我有很多业务工作流是在扣子平台上做的,两者打通之后,就可以在扣子空间里直接通过对话方式调用扣子工作流了&#xff0…

SpringBoot基础项目搭建

资料链接:https://download.csdn.net/download/ly1h1/90855288?spm1001.2014.3001.5501 1.准备工作 1.1 安装IntelliJ IDEA 2023.3.4 (Ultimate Edition) 1.2 采用apache-maven-3.6.3 1.2.1 maven配置文件设置 1.2.2 IDEA配置maven 1.3 JDK采用17版本 2.手动创建…

【拥抱AI】Deer-Flow字节跳动开源的多智能体深度研究框架

最近发现一款可以对标甚至可能超越GPT-Researcher的AI深度研究应用,Deer-Flow(Deep Exploration and Efficient Research Flow)作为字节跳动近期开源的重量级项目,正以其模块化、灵活性和人机协同能力引发广泛关注。该项目基于 La…

前端获取用户的公网 IP 地址

可以使用免费的免费的公共服务网站 一:https://www.ipify.org/ 获取 JSON 格式的 IP 地址 // 旧地址不好使 // https://api.ipify.org/?formatjson // 新地址 https://api64.ipify.org/?formatjson 二:https://ipinfo.io/ https://ipinfo.io/ 三&a…

云电竞服务器 工作原理

云电竞服务器工作原理详解 一、核心架构原理 虚拟化资源池‌ 通过 ‌KVM/VMware‌ 等虚拟化技术将物理服务器(含NVIDIA GPU集群)抽象为可动态分配的算力资源池,每个用户独享独立虚拟机实例,实现硬件资源的按需分配与隔离运行。 …

【数据结构】线性表--队列

【数据结构】线性表--队列 一.什么是队列二.队列的实现1.队列结构定义:2.队列初始化函数:3.队列销毁函数:4.入队列函数(尾插):5.出队列函数(头删):6.取队头元素&#xff…