⑥. watch dog自动延期机制
(客户端A加锁成功,就会启动一个watch dog看门狗,他是一个后台线程,会每隔10秒检查一下,如果客户端A还持有锁key,那么就会不断的延长锁key的生存时间,默认每次续命又从30秒新开始)
- ⑦. 详解缓存续命源码解析四:加锁逻辑(针对于默认时间30s过期的) lock.lock()
- 没有锁,加锁(唯一的id),启动定时任务,设置30s的过期时间
- 有锁:将唯一id+1(可重入锁)
- 非加锁线程,返回当前加锁线程的过期时间
- ⑧. 详解缓存续命源码解析五:解锁逻辑
- 如果释放的锁的线程和已存在锁的线程不是同一个线程,返回null
- 通过hincrby递减1,先释放一次锁。若剩余次数还大于0,则证明当前锁是可重入锁,刷新过期时间
- 若剩余次数小于0,删除key并释放锁,解锁成功
⑨. 详解缓存续命源码解析六:加锁逻辑
(lock.lock(10,TimeUnit.SECONDS):10s自动解锁,不会自动续期)
底层原理:如果我们传递了锁的超时时间,就发送给redis执行lua脚本,进行占锁,默认超时就是我们指定的时间
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) { this.internalLockLeaseTime = unit.toMillis(leaseTime); return this.evalWriteAsync(this.getName(), 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.getName()), this.internalLockLeaseTime, this.getLockName(threadId)); }