深入解析 Redisson分布式锁看门狗机制

一、Redisson分布式锁概述

1.1 分布式锁的意义

在分布式系统中,多个节点可能同时访问共享资源,导致数据不一致或竞态条件。分布式锁通过协调不同节点对共享资源的访问,确保数据的一致性和并发访问的安全性。

1.2 Redisson分布式锁的优势

  • 基于Redis实现:Redis作为高性能的内存数据库,提供了快速、稳定的存储服务,为Redisson分布式锁提供了坚实的基础。
  • 丰富的API:Redisson提供了丰富的Java API,使得分布式锁的使用更加简单、直观。
  • 自动续期机制:Redisson的分布式锁支持自动续期,避免了因业务处理时间过长导致的锁过期问题。
  • 可重入锁:Redisson的分布式锁支持可重入特性,即同一个线程可以多次获取同一把锁。

二、Redisson分布式锁的原理

2.1 锁的实现方式

Redisson分布式锁主要基于Redis的SETNX(Set if Not Exists)命令和DEL(Delete)命令实现。SETNX命令尝试设置一个值,如果该键不存在,则设置成功并返回1;否则返回0DEL命令则用于删除一个键。

2.2 看门狗机制

  • Redisson通过看门狗(Watch Dog)机制来实现锁的自动续期。当一个没有 leaseTime线程获取锁后,Redisson会立即启动一个后台的定时任务(看门狗)来定期检查锁的状态。
  • 看门狗的时间间隔通常是锁默认过期时间 (如30秒)的三分之一(即10秒)。这意味着,在锁的默认过期时间到达之前,看门狗会至少检查两次锁的状态,并在需要时自动续期。
  • 如果线程在锁的默认过期时间内完成了操作并释放了锁,看门狗会检测到锁的释放并取消该定时任务,避免不必要的资源消耗。
  • 看门狗机制只会针对没有设置 leaseTime 的锁;设置了 leaseTime 的锁不会有看门狗机制,会根据设置的过期时间自然过期。

2.3 锁的自动续期机制

  • 当看门狗检测到锁即将过期(即在当前锁的剩余时间小于看门狗的时间间隔)时,它会尝试自动续期。续期操作会延长锁的过期时间,确保在锁还在使用的情况下,其他线程无法获取到该锁。
  • 续期的时间长度通常是锁的默认过期时间(如再次设置为30秒),但也可以根据具体需求进行调整。

2.4 锁的释放

当一个线程完成临界区的操作后,应当手动释放锁。在Redisson中,这通常通过调用unlock()方法来完成。如果线程没有手动释放锁,而是异常结束或被其他方式中断,Redis的键空间通知功能可以确保锁在一段时间后自动释放。

三、Redisson 看门狗机制

3.1 参数说明

  • waitTime: 表示在尝试获取锁之前,线程会等待多长时间。当waitTime设置为大于0的值时,线程在尝试获取锁时会在指定的时间内等待。如果在这段时间内锁没有被获取到,tryLock方法将返回false。

  • leaseTime: 表示锁的持有时间,即锁在自动释放之前可以保持多久。

  • unit: 时间单位,用于指定waitTime和leaseTime的时间单位。

3.2 举例几个常见的方法

typescript 复制代码
	RLock lock = redissonClient.getLock("lockKey001");

	// 没设置leaseTime,有看门狗机制
	lock.tryLock();
	// 实际调用的RedissonLock的tryLock(long waitTime, TimeUnit unit) 
	// 没设置leaseTime,有看门狗机制
	lock.tryLock(3, TimeUnit.SECONDS); 
	// 实际调用的RedissonLock的lock(long leaseTime, TimeUnit unit)方法
	// 设置了leaseTime,有看门狗机制
	lock.lock(10, TimeUnit.SECONDS);
	// 设置了leaseTime=10s,没有看门狗机制
	lock.tryLock(3,10, TimeUnit.SECONDS);

3.3 tryLock()

tryLock() 方法默认会有看门狗机制,因为没有设置过期时间,默认是30s过期,但是看门狗每10s续期一次,每次续期都重新设置过期时间为30s。如果没有释放锁,理论上会无限续期。

3.4 tryLock(long waitTime, TimeUnit unit)

typescript 复制代码
// 源码
 public boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException {
        return this.tryLock(waitTime, -1L, unit);
    }

因为这个方法没有设置 leaseTime,因此默认也是有看门狗机制的。默认是30s过期,但是看门狗每10s续期一次,每次续期都重新设置过期时间为30s。如果没有释放锁,理论上会无限续期。

3.5 lock(long leaseTime, TimeUnit unit)

设置了 leaseTime 不会有看门狗机制

typescript 复制代码
 // 源码
 public void lock(long leaseTime, TimeUnit unit) {
        try {
            this.lockInterruptibly(leaseTime, unit);
        } catch (InterruptedException var5) {
            Thread.currentThread().interrupt();
        }
    }

3.6 tryLock(long waitTime, long leaseTime, TimeUnit unit)

设置了 leaseTime 不会有看门狗机制

typescript 复制代码
// 源码
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
	long time = unit.toMillis(waitTime);
	long current = System.currentTimeMillis();
	...........
}

四、其他

4.1 看门狗生命周期

当一个没有设置leaseTime 的锁一创建 Redisson 就会生成一个对应的看门狗,如果执行了unlock()则看门狗会一起销毁。不然会直到java进程终止(重启、销毁)才会消失。

4.2 看门狗是Redisson 生成的吗

是的,看门狗机制是Redisson 后台启的一个定时任务,不是Redis自带的。

相关推荐
爱的叹息30 分钟前
spring boot集成reids的 RedisTemplate 序列化器详细对比(官方及非官方)
redis
weitinting1 小时前
Ali linux 通过yum安装redis
linux·redis
纪元A梦2 小时前
Redis最佳实践——首页推荐与商品列表缓存详解
数据库·redis·缓存
爱的叹息9 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
松韬10 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
天上掉下来个程小白10 小时前
Redis-14.在Java中操作Redis-Spring Data Redis使用方式-操作列表类型的数据
java·redis·spring·springboot·苍穹外卖
·云扬·11 小时前
深度剖析 MySQL 与 Redis 缓存一致性:理论、方案与实战
redis·mysql·缓存
汤姆大聪明11 小时前
Redisson 操作 Redis Stream 消息队列详解及实战案例
redis·spring·缓存·maven
csjane10791 天前
Redis原理:rename命令
java·redis
Chandler241 天前
Redis:内存淘汰原则,缓存击穿,缓存穿透,缓存雪崩
数据库·redis·缓存