RedissonLock-tryLock-续期

redisson版本3.16.6

1.什么是看门狗

Redisson提供的分布式锁是支持锁自动续期的,也就是说,如果线程仍旧没有执行完,那么redisson会自动给redis中的目标key延长超时时间,这在Redisson中称之为 Watch Dog 机制。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

2.什么情况会续期

什么情况会续期,总结一句话: 不传入leaseTime( 锁自动释放时间**),使用默认值-1**

tryLock可传入参数有三个

lockName需要锁住的内容关键字

waitTime 获取锁最大等待时间,没有传-1

leaseTime锁自动释放时间,没有传-1

boolean tryLock 重载了三个方法,分别如下:

java 复制代码
boolean tryLock(String lockName);

boolean tryLock(String lockName, long waitTime) throws InterruptedException;

boolean tryLock(String lockName, long waitTime, long leaseTime) throws InterruptedException;

从实现上看,使用才传参,不用,千万别主动写入-1,会对入参有校验。可以实现续期的情况只能使用前两个构造器,不能使用主动传入leaseTime的构造器。为什么这么说呢,源码如下:

方法都会调用tryLock获取锁,tryLock方法中调用tryAcquire方法

java 复制代码
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    long time = unit.toMillis(waitTime);
    long current = System.currentTimeMillis();
    long threadId = Thread.currentThread().getId();
    Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
    // lock acquired
    if (ttl == null) {
        return true;
    }
        ....省略

tryAcquire方法会调用tryAcquireAsync,源码如下:

java 复制代码
private <T> RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {
    RFuture<Long> ttlRemainingFuture;
    if (leaseTime != -1) {
        ttlRemainingFuture = tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
    } else {
        ttlRemainingFuture = tryLockInnerAsync(waitTime, internalLockLeaseTime,
                TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
    }
    ttlRemainingFuture.onComplete((ttlRemaining, e) -> {
        if (e != null) {
            return;
        }

        // lock acquired
        if (ttlRemaining == null) {
            if (leaseTime != -1) {
                internalLockLeaseTime = unit.toMillis(leaseTime);
            } else {
                scheduleExpirationRenewal(threadId);
            }
        }
    });
    return ttlRemainingFuture;
}

从源码上看,只有当leaseTime为-1时scheduleExpirationRenewal这个方法才会生效,这个方法会进行续期。

3.续期源码分析

启一个task任务进行锁的自动续期

scheduleExpirationRenewal()->renewExpiration()

java 复制代码
private void renewExpiration() {
    ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());
    if (ee == null) {
        return;
    }

    // 启一个定时任务
    Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
        @Override
        public void run(Timeout timeout) throws Exception {
            ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());
            if (ent == null) {
                return;
            }
            Long threadId = ent.getFirstThreadId();
            if (threadId == null) {
                return;
            }

            // 核心续期代码,执行lua脚本
            RFuture<Boolean> future = renewExpirationAsync(threadId);
            future.onComplete((res, e) -> {
                if (e != null) {
                    log.error("Can't update lock " + getRawName() + " expiration", e);
                    EXPIRATION_RENEWAL_MAP.remove(getEntryName());
                    return;
                }

                if (res) {
                    // renewExpirationAsync执行成功,进行递归调用,调用自己,就可以实现不停的续期
                    // 第一次执行这个函数,设置task任务,10s后执行task任务,刷新有效期,又重新设置一个task任务,10s后执行
                    renewExpiration();
                } else {
                    cancelExpirationRenewal(null);
                }
            });
        }
        // 定时任务是lockWatchdogTimeout的1/3时间去执行,就是每10s执行一次,renewExpirationAsync进行续期
    }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);

    ee.setTimeout(task);
}
相关推荐
极客先躯1 天前
高级java每日一道面试题-2024年10月27日-Redis篇-jedis和redisson有哪些区别?
分布式·redisson·jedis·redis篇·redis高级
李逍遙️3 天前
Redisson实现分布式锁
spring boot·分布式·redisson
幸运小锦李先生12 天前
基于RabbitMQ,Redis,Redisson,RocketMQ四种技术实现订单延时关闭功能及其相关优缺点介绍(以12306为主题)
redis·rabbitmq·rocketmq·redisson·1024程序员节
水w1 个月前
Redisson分布式锁
java·redis·分布式·后端·redisson
水w1 个月前
详细分析Redisson分布式锁中的renewExpiration()方法
java·开发语言·redis·分布式·redisson·
神的孩子都在歌唱1 个月前
Redisson分布式锁的概念和使用
java·redis·分布式·redisson
lazy★boy2 个月前
Redisson实现分布式锁
分布式锁·redisson
赵丙双2 个月前
猜测、实现 B 站在看人数
redis·redisson·b站·哔哩哔哩·在看人数·在线人数
施小楠3 个月前
关于redisson的序列化配置
java·redis·redisson
HumoChen993 个月前
项目中引入RedisTemplate和Redisson时RedisTemplate无法使用zset问题(栈溢出stackOverflow)深入源码分析解决
java·spring boot·mybatis·redisson·redistemplate