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";
}