Redisson-lock看门狗原理
8. 分布式锁和同步器 · redisson/redisson Wiki · GitHub
默认-1
传入自己的时间(此处为10
) 不会执行看门狗,不等于-1
,如果是默认的话,等于-1
进入tryLockInnerAsync
,发现直接执行脚本
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
return this.evalWriteAsync(this.getRawName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);", Collections.singletonList(this.getRawName()), new Object[]{unit.toMillis(leaseTime), this.getLockName(threadId)});
}
protected RFuture<Boolean> renewExpirationAsync(long threadId) {
return this.evalWriteAsync(this.getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('pexpire', KEYS[1], ARGV[1]); return 1; end; return 0;", Collections.singletonList(this.getRawName()), this.internalLockLeaseTime, this.getLockName(threadId));
}
- 锁的自动续期,如果业务超长,运行时间自动给锁续上新的
30
秒。不用担心业务时间长。 - 加锁的任务只要运行完成,就不会给当前锁续期,即使不手动删锁。锁默认
30
秒后删除
lock.lock(10, TimeUnit.SECONDS);
10
秒钟自动解锁,自动解锁时间一定要大于业务时间
问题:lock.lock()
;在锁时间到了以后,不会自续期
-
1、如果我们传递了锁的超时时间,就发送给
redis
脚本,进行占锁,默认超时时间就是我们设置的时间 -
2、如果我们未指定锁的超时时间,就使用
30*1000
(LockWatchdogTimeout
看门狗的默认时间);
只要占锁成功,leaseTime=-1
就会启动一个定时任务- [重新给锁设置过期时间,新的过期时间就是看门狗的默认时间
30s
],每隔10s
都会自动续期30s
internalLockLeaseTime(看门狗时间)/3,10s
- [重新给锁设置过期时间,新的过期时间就是看门狗的默认时间
@ResponseBody
@GetMapping("/hello")
public String hello(){
//1、获取一把锁,只要锁的名字一样,就是同一把锁
RLock lock = redissonClient.getLock("myLock");
//2、加锁
lock.lock();//阻塞式等待,没拿到锁,一直等待。默认加锁30秒
//最佳实战
// lock.lock(10, TimeUnit.SECONDS);//10秒钟自动解锁,自动解锁时间一定要大于业务时间
// 省掉了整个续期操作。手动解锁
try {
System.out.println("加锁成功,执行业务"+Thread.currentThread().getId());
Thread.sleep(30000);
} catch (InterruptedException e) {
} finally {
//3、解锁,假设解锁代码没有运行,redisson会不会出现死锁
System.out.println("释放锁"+Thread.currentThread().getId());
lock.unlock();
}
return "hello";
}