Redisson 可重入分布式锁底层原理详解
一、什么是可重入锁可重入同一个线程在已经持有锁的前提下可以再次获取同一把锁不会出现自己把自己阻塞死的情况。本地锁中ReentrantLock、synchronized都是可重入锁。 而我们手写的简易 Redis 锁默认不支持可重入 线程拿到锁之后再次执行加锁代码会直接获取锁失败造成死锁。 所以生产环境分布式锁一般要求支持可重入Redisson 的 RLock 就是可重入分布式锁。应用场景A 方法获取锁A 内部调用 B 方法B 方法也需要获取同一把锁此时就需要锁支持重入。二、Redisson 锁在 Redis 中的存储结构Redisson 底层不是简单的key-value字符串而是使用hash 哈希结构存储锁信息key: lock:goods:1001 hash field: 线程唯一标识uuid threadId hash value: 重入计数count示例lock:goods:1001 35678190-1234-4567-8888:thread-1 - 1key锁名称field标记哪个线程持有这把锁value重入次数每重入一次 count1释放一次 count-1整个 hash 还会设置过期时间加锁逻辑Lua 脚本Redisson 加锁、重入、释放全部依靠 Lua 脚本保证原子性。-- 判断锁key是否不存在 if (redis.call(exists, KEYS[1]) 0) then -- 不存在新增hash计数1设置过期时间 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 -- 是当前线程计数1返回nil加锁成功 redis.call(hincrby, KEYS[1], ARGV[2], 1); redis.call(pexpire, KEYS[1], ARGV[1]); return nil; end; -- 锁存在且不是当前线程持有返回锁剩余过期时间加锁失败 return redis.call(pttl, KEYS[1]);参数说明KEYS[1]锁 keyARGV[1]锁过期时间毫秒ARGV[2]当前线程唯一标识uuid:threadId流程解读如果锁不存在创建 hash计数置 1设置过期时间加锁成功如果锁存在并且是当前线程的锁hincrby计数 1刷新过期时间重入成功如果锁存在但属于别的线程返回锁剩余有效期加锁失败三、释放锁 Lua 脚本释放锁不能直接 del要递减计数计数减到 0 才删除 key。-- 判断锁是否属于当前线程 if (redis.call(hexists, KEYS[1], ARGV[2]) 0) then return nil; end; -- 计数-1 local counter redis.call(hincrby, KEYS[1], ARGV[2], -1); if (counter 0) then -- 计数0说明还有重入只刷新过期时间不删除锁 redis.call(pexpire, KEYS[1], ARGV[1]); return 0; else -- 计数等于0删除锁key释放完成 redis.call(del, KEYS[1]); return 1; end;逻辑不是当前线程的锁直接返回禁止释放别人的锁计数 - 1计数 0还有重入锁不删除更新过期时间计数 0删除锁 key锁完全释放四、看门狗 WatchDog 自动续期机制重点面试题什么时候开启看门狗当你调用lock.lock()不指定过期时间Redisson 会自动启动看门狗如果手动指定 leaseTime看门狗不会自动开启需要自己处理锁超时风险。默认规则锁默认过期时间30s看门狗定时任务每 10s 执行一次过期时间的 1/3定时任务逻辑检查锁是否还被当前线程持有持有则刷新锁过期时间回到 30s原理获取锁成功后开启一个异步定时线程不断延长锁有效期。只要业务没执行完毕锁就不会过期业务执行结束锁释放看门狗任务停止。⚠️注意如果 JVM 宕机看门狗线程直接停止锁会等待过期自动释放不会永久死锁。手动指定 leaseTimeRedisson 认为用户自己管控过期不会启动看门狗业务执行时间不能超过 leaseTime。五、Redisson 代码演示1. maven 依赖dependency groupIdorg.redisson/groupId artifactIdredisson-spring-boot-starter/artifactId version3.17.7/version /dependency2. Redisson 配置类Configuration public class RedissonConfig { Bean public RedissonClient redissonClient(){ Config config new Config(); config.useSingleServer() .setAddress(redis://127.0.0.1:6379); return Redisson.create(config); } }3. 可重入锁业务代码Autowired private RedissonClient redissonClient; public void methodA(){ RLock lock redissonClient.getLock(lock:goods); try { // 不指定过期时间自动开启看门狗 lock.lock(); System.out.println(方法A获取锁成功); methodB(); //内部调用方法B再次获取同一把锁重入生效 }finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } public void methodB(){ RLock lock redissonClient.getLock(lock:goods); try { lock.lock(); System.out.println(方法B重入获取锁成功); }finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); } } }调用methodA()A 拿到锁调用 BB 再次获取同一锁计数 1释放时 A、B 各 unlock 一次计数归零锁删除。tryLock 非阻塞获取锁// 最多等待10s锁持有30s这里手动指定持有时间看门狗失效 boolean success lock.tryLock(10,30, TimeUnit.SECONDS);六、Redisson 锁存在的问题主从架构锁失效Redis 主从同步是异步复制主节点执行 Lua 脚本加锁成功返回客户端锁数据还没同步到从节点主节点宕机从节点升级为新 master新主没有锁数据其他线程可以再次获取锁锁失效并发安全被破坏解决方案RedLock 红锁多独立 redis 节点过半节点加锁成功才算获取锁。缺点运维成本高生产极少使用。业务层兜底数据库唯一索引、乐观锁、幂等防止超卖、重复下单。七、面试高频问答Q1Redisson 可重入锁底层怎么实现底层使用 Redis Hash 结构存储锁field 存线程唯一标识value 存储重入计数。加锁、释放锁全部使用 Lua 脚本保证原子操作同一线程多次加锁计数累加多次释放计数递减计数归零才删除锁 key。Q2看门狗什么时候生效原理是什么调用不带过期时间的lock.lock()时自动开启默认 30s 过期每 10s 刷新锁过期时间。业务执行完毕释放锁看门狗停止。JVM 宕机看门狗停止锁到期自动释放。Q3tryLock 指定 leaseTime看门狗还会工作吗不会。手动指定锁过期时间Redisson 认为开发者自行管理锁生命周期不会启动看门狗续期。业务执行时长不能超过 leaseTime。Q4为什么释放锁前要判断 isHeldByCurrentThread ()如果业务异常锁已经过期自动释放其他线程拿到锁。此时执行 unlock 会释放别人的锁isHeldByCurrentThread()校验锁持有者只有当前线程持有锁才允许解锁。Q5Redisson RLock 是公平锁吗默认是非公平锁也支持公平锁getFairLock()底层用 list 队列记录等待线程按照先来后到获取锁性能比非公平锁差。八、总结Redisson 可重入锁底层基于 Redis Hash Lua 脚本实现支持重入计数看门狗自动续期解决业务执行时间超过锁过期时间的问题加锁、释放全程 Lua保证命令原子性避免手写锁的各种坑主从异步复制场景下依然存在锁失效风险核心业务需要数据库兜底开发优先使用 Redisson不要手写 Redis 分布式锁。

相关新闻

Ant Design Blazor 图表系列:百分比堆叠条形图(Percent Stacked Bar)实战指南

Ant Design Blazor 图表系列:百分比堆叠条形图(Percent Stacked Bar)实战指南

UI组件前端 【免费下载链接】ant-design-blazor 🌈A rich set of enterprise-class UI components based on Ant Design and Blazor. 项目地址: https://gitcode.com/gh_mirrors/an/ant-design-blazor 点击查看 免费下载 百分比堆叠条形图(P…

2026/10/11 10:37:20 阅读更多 →
第 8 章 · 串起前 7 个:你的第一个「AI 百宝箱」脚本

第 8 章 · 串起前 7 个:你的第一个「AI 百宝箱」脚本

🎬 生活化引入前 7 章你其实已经偷偷攒了一整套"兵器":能聊天、能写小红书文案、能接微信、能摘要、能翻译、能讲段子、还能画张图。但老实说——它们现在像一堆散落在地上的乐高,想玩的时候还得一个个翻出来拼。我一个朋友就是这样…

2026/10/11 10:37:24 阅读更多 →
MySQL教学库samp_db导入实战:从ZIP解压到验证的完整避坑指南

MySQL教学库samp_db导入实战:从ZIP解压到验证的完整避坑指南

简介:这份资源是MySQL第五版配套的samp_db示例数据库ZIP压缩包,面向数据库初学者、高校学生及需要SQL实战练习的开发者,用于在真实表结构上理解关系型数据库的设计与查询。压缩包共0个文件(上游未提供明细)&#xff0c…

2026/10/11 10:37:27 阅读更多 →

最新新闻

MT6701磁性角度传感器:替代光电编码器的理想方案

MT6701磁性角度传感器:替代光电编码器的理想方案

简介:MT6701中文版数据手册是一份面向电机控制、机器人关节及非接触式旋钮等应用的磁性角度传感器技术文档,适合嵌入式工程师、硬件开发者及电子相关专业学生阅读参考。资源包含1个PDF文件,压缩包整体大小1.27MB,完整收录芯片的引…

2026/10/11 18:51:05 阅读更多 →
SpringBoot+Vue秒杀管理系统:高并发防超卖与订单管理实战

SpringBoot+Vue秒杀管理系统:高并发防超卖与订单管理实战

秒杀系统是Java后端实战里绕不开的经典场景,这个基于SpringBootVue的管理系统恰好覆盖了秒杀业务从用户登录、商品列表、定时抢购、库存扣减到订单管理和后台维护的完整闭环,技术栈则是地道的JavaMySQLMyBatis,再配一套Vue前端。很多人看着“…

2026/10/11 18:51:05 阅读更多 →
5分钟搭建生产级文档网站:Blume从init到build的新手快速入门教程

5分钟搭建生产级文档网站:Blume从init到build的新手快速入门教程

【免费下载链接】blume The open-source docs framework for humans and agents. 项目地址: https://gitcode.com/gh_mirrors/blum/blume 点击查看 免费下载 Blume 是一个开源文档框架(docs framework),专为人类和 AI Agent 设计…

2026/10/11 18:51:05 阅读更多 →
Oracle EBS财务模块实战:GL、AP、CST与PAC成本核算避坑指南

Oracle EBS财务模块实战:GL、AP、CST与PAC成本核算避坑指南

简介:Oracle EBS财务模块学习资料,面向ERP初学者、财务信息化从业者及企业财务管理人员,帮助系统理解Oracle电子商务套件在财务管理领域的核心功能与实施思路。资料以docx文档形式呈现,压缩包内共1个文件,约32KB&#…

2026/10/11 18:51:05 阅读更多 →
SAP Data Services 连接 MySQL 失败排查:驱动、DSN 与 Job Server 实战指南

SAP Data Services 连接 MySQL 失败排查:驱动、DSN 与 Job Server 实战指南

简介:《SAP Data Services如何连接MySQL》是一份面向数据集成工程师、ETL开发及SAP BI实施人员的实操指南,重点解决在Business Objects Data Services中从零配置MySQL数据源的流程痛点。文档基于完整截图与步骤拆解,详细演示了新建data store…

2026/10/11 18:51:05 阅读更多 →
异或运算解算法题:只出现一次的数字的位运算原理与实现

异或运算解算法题:只出现一次的数字的位运算原理与实现

每次有人让我推荐值得反复琢磨的算法题,我几乎都会提到"只出现一次的数字"这道题。题目本身非常短:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次,找出那个只出现一次的元素&…

2026/10/11 18:50:05 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →