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

Redisson 分布式锁实现:可重入与看门狗

引言

在分布式架构中,多台服务器共享同一资源时,传统的 JVM 锁已无法保障数据一致性,分布式锁由此成为关键。Redisson 基于 Redis 实现的分布式锁,不仅支持可重入、自动续期,还通过发布订阅机制高效处理锁竞争。本文从加锁、锁续命、锁释放三个环节,深入解析 Redisson 的核心设计,包括 Lua 脚本保证原子性、Watch Dog 看门狗的定时续期机制,以及如何灵活控制锁的失效策略。

Redisson分布式锁实现

分布式锁是为了解决分布式架构中多台服务器共享资源的并发问题,单体时代可以使用JVM锁解决并发问题,但分布式架构中,同时存在多台服务器执行同样的逻辑,也就是在多套JVM环境下执行同样的逻辑,此时JVM锁无法生效,所以需要分布式锁。

加锁过程

还未加锁

  1. 先判断是否存在key为KEYS[1]的键值对(==0表示不存在),如果不存在表示未加锁。

  2. 通过hset(Hash结构)设置<锁名称, <UUID + 线程ID, 1>>,KEYS[1] = 锁名称,ARGV[2] = UUID + 线程ID。

  3. 通过pexpire设置key的过期时间,默认30s。

已经加锁

  1. 通过hexists(Hash结构)判读前线程是否加锁成功,如果当前线程加锁成功走2。

  2. 给当前线程的value+1。

  3. 在次通过pexpire设置key的过期时间,默认30s。

加锁失败

  1. 通过ttl返回剩余过期时间,方便后续线程重试去竞争锁,如果加锁成功则返回null。

  2. 加锁失败后会订阅频道(redisson_lock__channel + lockName)返回一个Future用于获得锁释放通知,并通过Semaphore.tryAcquire(ttl, TimeUnit.MILLISECONDS)在ttl时间内尝试获取一个信号量许可,获取到信号量许可后再次进行锁竞争,直至成功。

锁续命过程

使用锁续命而不是不限时的锁,是为了防止用户线程崩溃,导致锁一直未释放。所以每隔一段时间进行锁的续命,而不是设置永久锁,这样即便用户线程崩溃,也只是30s,无法访问。

  1. 锁续命需要判断用户是否设置过期时间,如果设置了过期时间,不会进行锁续命。

  2. 通过定时任务每30/3秒,找到当前线程对应的锁,如果存在重新设置过期时间为30秒。

锁释放过程

  1. 判断线程id(小key)是否存在,如果不存在,则返回null;如果存在,则可重入次数-1。

  2. 再判断可重入次数是否 > 0,如果 > 0,则不能释放锁,并重新设置锁过期时间。

  3. 如果 <= 0,则删除redis的大key,往(redisson_lock__channel + lockName)频道发送message,发送UNLOCK_MESSAGE。

Watch Dog(看门狗)

看门狗如何实现锁续期的?

第一次进入的时候,这里放进去的就是一个全新的ExpirationEntry类,并进行续约操作。续约操作其实就是创建一个延迟任务,默认每10s执行一次,延迟任务由HashedWheelTimer实现,核心是时间轮算法

如何修改看门狗续期时间?

配置lockWatchdogTimeout参数,可以调整看门狗续期频率和续期时间,默认lockWatchdogTimeout/3秒自动需求。

Config config = new Config(); config.setLockWatchdogTimeout(60000); // 设置为 60 秒

如何设置看门狗不会续期?

指定leaseTime参数,这表示锁的有效期。在这个时间之后,如果没有主动释放,锁将自动失效并释放资源。

RLocklock= redissonClient.getLock("myLock"); // 试图加锁,锁的过期时间设置为10秒钟 lock.lock(10, TimeUnit.SECONDS);

情况下,Redisson的看门狗机制会停止续期?

  • 第一种情况:手工调用停止续期方法即cancelExpirationRenewal(),看门狗机制会停止续期。

  • 第二种情况:调用unlock()释放分布式锁后,看门狗机制也会停止续期。

  • 第三种情况:如果尝试续期的过程中,当前线程被中断,看门狗机制也会停止续期。

  • 第四种情况:应用程序宕机或者进程被kill掉,看门狗机制也会停止续期。


感谢您的阅读!如果文章中有任何问题或不足之处,欢迎及时指出,您的反馈将帮助我不断改进与完善。期待与您共同探讨技术,共同进步!

http://www.cnnetsun.cn/news/2171929.html

相关文章:

  • 嵌入式Linux开发板深度定制:从内核驱动到根文件系统构建实战
  • 支付宝异步通知处理库alipay-notify:安全验签与生产环境实践指南
  • Windows Cleaner:告别C盘爆红的智能系统清理神器
  • 从Arduino到STM32:用AS5600磁编码器做个角度传感器,附完整代码与精度对比
  • TMC2240 芯片数据手册解读|第七篇 步进/方向接口(Step/Direction Interface)全解析
  • Gemini 3.1 在线入口(官方镜像):为什么它被持续关注
  • 64、【Agent】【OpenCode】用户对话提示词(推理链)
  • Gemini 官方下载,安全无病毒
  • 绝地求生压枪难题怎么破?罗技鼠标宏5分钟配置指南
  • 如何快速解决Windows任务栏透明工具TranslucentTB启动失败问题:完整解决方案指南
  • ViGEmBus:Windows内核级虚拟游戏控制器驱动深度解析
  • 基于STM32单片机智能出租车计价器分时计费GPS定位蓝牙设计23-135
  • BV哔哩哔哩第三方客户端TV车机版 支持4K真彩HDR|杜比视界 精简11M安装包
  • 魔兽争霸3玩家必备:9大兼容性问题一站式解决方案
  • 基于Claude API的智能代理框架:从工具调用到生产部署全解析
  • Maya glTF插件:5步实现3D模型跨平台完美转换
  • Spark.NET:一个试图把 Django / Rails 式开发体验带回 .NET 世界的全栈 Web 框架。
  • 为 OpenClaw 智能体配置 Taotoken 作为其底层模型服务
  • 如何智能清理Windows系统:免费开源工具的高效使用指南
  • 前端开发必备:shameless工具库深度解析与实战应用
  • 变长序列数据处理:从填充掩码到动态批处理实战
  • 从零构建Vue 3组件库:Monorepo架构与Vite工程化实践
  • 内存泄漏?连接漂移?超时熔断失效?Swoole-LLM长连接三大致命故障全解析,附GDB+eBPF实时诊断脚本
  • 别再乱用网络标号了!Altium Designer多页原理图连接,用对Port和Sheet Entry才算入门
  • 蛋白质结构预测:从AlphaFold2到SimpleFold的技术革新
  • 告别输入法词库迁移烦恼:深蓝词库转换工具完全指南
  • 智慧树自动刷课插件:如何让网课学习效率提升3倍?
  • 中之网:构建“官网+短视频+AI大模型”全域营销矩阵,抢占电机行业智能搜索新蓝海
  • GitHub 热门项目 `modded-nanogpt` 实测:把“90 秒训练 124M”搬到 RTX 3090 后,先炸的不是显存,而是 Hopper 专用内核
  • 别再装错版本了!手把手教你用华为云镜像正确安装d2l 0.17.6(附避坑指南)