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

Redisson分布式锁:看门狗机制与续期原理

文章目录

  • 前言
  • 一、分布式锁的基本概念
    • 1.1 什么是分布式锁
    • 1.2 为什么选择Redisson
  • 二、Redisson分布式锁的使用
    • 2.1 基本使用示例
    • 2.2 可重入锁示例
    • 2.3 看门狗机制的自动续期
  • 三、底层原理深度分析
    • 3.1 加锁原理
    • 3.2 解锁原理
    • 3.3 看门狗(WatchDog)机制
      • 3.3.1 看门狗的工作原理
      • 3.3.2 续期脚本
    • 3.4 可重入实现原理
    • 四、总结

前言

在微服务架构和分布式系统中,分布式锁是保证数据一致性的重要手段。Redis作为高性能的内存数据库,天然适合实现分布式锁。而Redisson作为Redis的Java客户端,不仅提供了完善的分布式锁实现,还引入了看门狗(WatchDog)机制来解决锁续期问题。

一、分布式锁的基本概念

1.1 什么是分布式锁

分布式锁是在分布式环境下,多个进程或线程对共享资源进行互斥访问的一种机制。它需要满足以下特性:

  • 互斥性:同一时刻只能有一个进程持有锁
  • 可重入性:同一线程可以多次获取同一把锁
  • 阻塞与非阻塞:获取不到锁时的处理策略
  • 容错性:具备自动释放锁的能力

1.2 为什么选择Redisson

相比于直接使用Redis命令实现分布式锁,Redisson提供了以下优势:

  • 自动续期:通过看门狗机制避免业务执行时间过长导致的锁自动释放
  • 可重入实现:支持同一线程多次获取同一把锁
  • 阻塞等待:提供tryLock等方法支持超时等待
  • Lua脚本:保证原子性操作

二、Redisson分布式锁的使用

2.1 基本使用示例

@Service
public class DistributedLockService {@Autowiredprivate RedissonClient redissonClient;public void processWithLock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);try {// 尝试获取锁,等待时间10秒,锁自动释放时间30秒boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);if (isLocked) {System.out.println("获取锁成功,开始处理业务逻辑");// 执行业务逻辑doBusinessLogic();System.out.println("业务逻辑处理完成");} else {System.out.println("获取锁失败");}} catch (InterruptedException e) {Thread.currentThread().interrupt();System.err.println("获取锁被中断");} finally {// 释放锁if (lock.isHeldByCurrentThread()) {lock.unlock();System.out.println("锁已释放");}}}private void doBusinessLogic() {try {// 模拟业务处理时间Thread.sleep(5000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

2.2 可重入锁示例

public class ReentrantLockDemo {private final RedissonClient redissonClient;private final RLock lock;public ReentrantLockDemo(RedissonClient redissonClient) {this.redissonClient = redissonClient;this.lock = redissonClient.getLock("reentrant:lock");}public void method1() {lock.lock();try {System.out.println("执行方法1");method2(); // 可重入调用} finally {lock.unlock();}}public void method2() {lock.lock(); // 同一线程再次获取锁try {System.out.println("执行方法2");method3();} finally {lock.unlock();}}public void method3() {lock.lock(); // 同一线程第三次获取锁try {System.out.println("执行方法3");} finally {lock.unlock();}}
}

2.3 看门狗机制的自动续期

public class WatchDogDemo {private final RedissonClient redissonClient;public WatchDogDemo(RedissonClient redissonClient) {this.redissonClient = redissonClient;}public void longRunningTask() {RLock lock = redissonClient.getLock("watchdog:lock");try {// 不指定锁的过期时间,启用看门狗机制lock.lock();System.out.println("开始执行长时间任务");// 模拟长时间运行的任务(超过默认锁过期时间30秒)for (int i = 0; i < 10; i++) {Thread.sleep(10000); // 每次休眠10秒System.out.println("任务进行中... " + (i + 1) * 10 + "秒");}System.out.println("长时间任务执行完成");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}}
}

三、底层原理深度分析

3.1 加锁原理

Redisson使用Lua脚本来保证加锁操作的原子性,核心脚本如下:

-- 加锁脚本
if (redis.call('exists', KEYS[1]) == 0) thenredis.call('hset', KEYS[1], ARGV[2], 1);redis.call('pexpire', KEYS[1], ARGV[1]);return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) thenredis.call('hincrby', KEYS[1], ARGV[2], 1);redis.call('pexpire', KEYS[1], ARGV[1]);return nil;
end;
return redis.call('pttl', KEYS[1]);

这个脚本的执行逻辑:

  1. KEYS[1]:锁的名称
  2. ARGV[1]:锁的过期时间(毫秒)
  3. ARGV[2]:线程标识(UUID + 线程ID)

执行流程:

  • 如果锁不存在,创建锁并设置过期时间
  • 如果锁存在且是当前线程持有,重入计数加1
  • 否则返回锁的剩余存活时间

3.2 解锁原理

解锁同样使用Lua脚本保证原子性:

-- 解锁脚本
if (redis.call('exists', KEYS[1]) == 0) thenreturn 1;
end;
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) thenreturn nil;
end;
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) thenredis.call('pexpire', KEYS[1], ARGV[2]);return 0;
elseredis.call('del', KEYS[1]);redis.call('publish', KEYS[2], ARGV[1]);return 1;
end;

解锁逻辑:

  • 锁不存在直接返回
  • 当前线程不持有锁返回null
  • 重入计数减1,如果大于0重新设置过期时间
  • 如果计数为0,删除锁并发布解锁消息

3.3 看门狗(WatchDog)机制

看门狗机制是Redisson的核心特性,解决了业务执行时间不确定导致的锁提前释放问题。

3.3.1 看门狗的工作原理

实现原理概览
看门狗机制本质上是一个 后台定时任务,它:

  1. 在成功获取锁后自动启动
  2. 每隔一段时间检查当前线程是否仍然持有锁
  3. 如果是,则向 Redis 发送命令延长锁的过期时间(TTL)
  4. 直到锁被显式释放(unlock())或客户端断开

3.3.2 续期脚本

-- 续期脚本
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) thenredis.call('pexpire', KEYS[1], ARGV[1]);return 1;
end;
return 0;

看门狗机制的关键点:

  1. 续期时机:每隔 lockLeaseTime/3 时间执行一次续期
  2. 续期条件:只有当前线程持有锁时才能续期成功
  3. 自动停止:锁释放时自动停止看门狗任务
  4. 默认时间:默认锁存活时间为30秒,续期间隔为10秒

3.4 可重入实现原理

Redisson使用Hash数据结构实现可重入:

锁的数据结构:
KEY: lock:mylock
VALUE: {"8743c9c0-0795-4907-87fd-6c719a6b4586:1": 3
}
  • KEY:锁的名称
  • Hash Field:客户端ID + 线程ID
  • Hash Value:重入次数

这种设计的优势:

  • 通过Hash结构存储线程标识和重入次数
  • 原子性操作保证数据一致性
  • 支持多线程并发访问不同的锁

四、总结

Redisson分布式锁通过以下几个关键机制实现了高可用、高性能的分布式锁方案:

  1. Lua脚本保证原子性:加锁、解锁、续期操作都通过Lua脚本实现原子性
  2. 看门狗机制解决续期问题:自动续期避免业务执行时间过长导致的锁丢失
  3. Hash结构实现可重入:使用Redis Hash存储线程信息和重入次数
  4. 发布订阅优化性能:通过Redis的pub/sub机制减少客户端轮询

文章转载自:

http://ACzhZqUt.gqtzb.cn
http://8Pk3BGAh.gqtzb.cn
http://8ycIuMY6.gqtzb.cn
http://ysIa8MQ4.gqtzb.cn
http://Qd4vAQfw.gqtzb.cn
http://RxCc4ucv.gqtzb.cn
http://j8NbPU1h.gqtzb.cn
http://oCuNZGMg.gqtzb.cn
http://tLTBUL57.gqtzb.cn
http://nlx6lsMd.gqtzb.cn
http://iGkME3Kd.gqtzb.cn
http://vDyiO11A.gqtzb.cn
http://HEBDhKFu.gqtzb.cn
http://UhWDkz6q.gqtzb.cn
http://6vwwmSVl.gqtzb.cn
http://LHSObw5S.gqtzb.cn
http://mg2pf1fC.gqtzb.cn
http://9gDgPd1J.gqtzb.cn
http://7NRfK5MU.gqtzb.cn
http://pm8ZwknJ.gqtzb.cn
http://G8ievJBE.gqtzb.cn
http://4in1ZOUX.gqtzb.cn
http://sNkr1FUf.gqtzb.cn
http://QZFojqZ1.gqtzb.cn
http://kfQOkuiy.gqtzb.cn
http://aWLpGdzB.gqtzb.cn
http://57dKYc4f.gqtzb.cn
http://c9M5YSCH.gqtzb.cn
http://4OjMwig8.gqtzb.cn
http://BpOLeRmm.gqtzb.cn
http://www.dtcms.com/a/370653.html

相关文章:

  • OSG工具集
  • CC内存管理深度解析从内存布局到newdelete的底层实现
  • 让机器具有主动性-主动性算法[01]
  • PagedAttention:突破大语言模型内存瓶颈的分页式注意力革命
  • Qt 中的 Q_OBJECT 宏详解 —— 从源码到底层机制的全面剖析
  • 正态分布 - 计算 Z-Score 的 无偏估计
  • 【基础-单选】用哪一种装饰器修饰的struct表示该结构体具有组件化能力?
  • 【LeetCode 每日一题】2348. 全 0 子数组的数目
  • 《2025国赛/高教杯》C题 解题思路 NIPT的时点选择与胎儿的异常判定
  • vspere 服务的部署介绍
  • 基本数据类型和包装类的区别?
  • 《AC影》正史模式引争议 育碧回应希望激发历史兴趣
  • leetcode30.串联所有单词的子串
  • QML Charts组件之LineSeries、SplineSeries与ScatterSeries
  • browser-use 的三种启动方式详解
  • Qt对话框与文件操作学习
  • Linux文件管理器选择与推荐
  • 接雨水问题解析:双指针与单调栈解法
  • Kafka Exactly-Once 语义深度解析与性能优化实践指南
  • spring-ai-alibaba-deepresearch 学习(十三)——ResearcherNode
  • 2、数学与经济管理
  • 使用 Shell 脚本监控服务器 IOWait 并发送邮件告警
  • Python数据可视化科技图表绘制系列教程(六)
  • [Upscayl图像增强] docs | 前端 | Electron工具(web->app)
  • 同态加密库(Google FHE)
  • Qt自定义列表项与QListWidget学习
  • MySQL 高可用方案之 MHA 架构搭建与实践
  • 天津大学2024-2025 预推免 第一批机试题目纯暴力题解
  • 金属也有“记忆力”?—聊聊二合一玛哈特矫平机如何“消除”金属的记忆
  • 基于阿里云ECS搭建Tailscale DERP中继服务器:提升跨网络连接速度