文章目录

redisson看门狗机制

官网解释

Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

看门狗开启条件

我们可以看到,leaseTime != -1时,只执行tryLockInnerAsync方法,其它情况会执行下面的代码,而leaseTime 就是我们调用
lock(10, TimeUnit.SECONDS);方法传入的时间参数。

由此可知:redisson如果只是用lock.lock();不传过期时间的话,会启动看门狗机制,传过期时间的话,就不会启动看门狗机制。

// org.redisson.RedissonLock#tryAcquireAsync
private <T> RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {
if (leaseTime != -1) {
return tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
}
RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(waitTime,
commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(),
TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
// future模式,抢到锁之后开启看门狗
ttlRemainingFuture.onComplete((ttlRemaining, e) -> {
if (e != null) {
return;
}

// lock acquired
if (ttlRemaining == null) {
scheduleExpirationRenewal(threadId); // 开启看门狗
}
});
return ttlRemainingFuture;
}

看门狗如何开启的

以下代码就是开启看门狗的方法,我们可以看到,启动了一个TimerTask进行倒计时,默认倒计时时间为internalLockLeaseTime / 3,也就是默认的10秒钟(默认过期时间是30秒)。

// org.redisson.RedissonLock#renewExpiration
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 " + getName() + " expiration", e);
return;
}

if (res) {
// reschedule itself
renewExpiration(); // 不断地调用自己,刷新过期时间
}
});
}
}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);

ee.setTimeout(task);
}

看门狗的性能问题

很多小伙伴都认为看门狗是非常消耗性能的,其实性能的确是会有一些消耗,但是没有很多。
前几天有个小伙伴抛出了一个疑问:假如说每个线程都启动一个TimerTask来不断刷新过期时间,岂不是服务器很快就“炸了”?

其实不然,只有抢占到锁的线程才会开启看门狗,并不是每个等待的线程都会开启一个看门狗。也就是说——基本上每一个锁会对应一个看门狗,而不是每一个线程对应一个看门狗。

这样看来,是不是性能浪费的就不是很多了?

其实看门狗机制主要是用于业务代码执行时间忽长忽短的,如果一个业务代码,我们确定它在10秒钟之内就会执行完毕,完全可以取消这个看门狗机制,来提升一部分性能。

强大的redisson

redisson非常强大,完美的解决了分布式系统下的很多问题。
具体请查阅文档:
​​​redisson使用全解——redisson官方文档+注释(上篇)​​​​redisson使用全解——redisson官方文档+注释(中篇)​​​​redisson使用全解——redisson官方文档+注释(下篇)​