redisson 分布式锁源码分析
时间: 2023-12-30 09:04:03 浏览: 100
Redisson是一个基于Redis的Java驻留库,提供了分布式和线程安全的Java数据结构。Redisson的分布式锁实现是基于Redis的setnx命令和Lua脚本实现的。下面是Redisson分布式锁的源码分析:
1.获取锁
Redisson的分布式锁获取方法是tryAcquire方法,该方法首先会尝试使用setnx命令在Redis中创建一个key,如果创建成功则表示获取锁成功,否则会进入自旋等待。在自旋等待期间,Redisson会使用watchDog机制来监控锁的状态,如果锁被其他线程释放,则会重新尝试获取锁。
2.释放锁
Redisson的分布式锁释放方法是release方法,该方法会使用Lua脚本来判断当前线程是否持有锁,如果持有锁则会使用del命令删除锁的key。
3.watchDog机制
Redisson的watchDog机制是用来监控锁的状态的,该机制会在获取锁时启动一个定时任务,定时任务会检查锁的状态,如果锁被其他线程释放,则会重新尝试获取锁。
```java
// 获取锁
public boolean tryAcquire(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long time = unit.toMillis(waitTime);
long current = System.currentTimeMillis();
final long threadId = Thread.currentThread().getId();
final long leaseTimeInMillis = unit.toMillis(leaseTime);
while (true) {
if (tryAcquire()) {
scheduleExpirationRenewal(threadId, leaseTimeInMillis);
return true;
}
time -= (System.currentTimeMillis() - current);
if (time <= 0) {
return false;
}
current = System.currentTimeMillis();
if (Thread.interrupted()) {
throw new InterruptedException();
}
// watchDog机制
RFuture<RedissonLockEntry> future = subscribe(threadId);
if (!future.await(time, TimeUnit.MILLISECONDS)) {
return false;
}
}
}
// 释放锁
public void unlock() {
if (isHeldByCurrentThread()) {
unlockInner();
}
}
private void unlockInner() {
Long ttl = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_LONG,
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 0) then return nil end; " +
"local counter = redis.call('hincrby', KEYS[1], ARGV[2], -1); " +
"if (counter > 0) then return 0 end; " +
"redis.call('del', KEYS[1]); " +
"redis.call('publish', KEYS[2], ARGV[1]); " +
"return 1;",
Arrays.<Object>asList(getName(), getChannelName()),
encode(new UnlockMessage(getName(), getLockName())),
id);
cancelExpirationRenewal();
if (ttl == null) {
throw new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: " + id + " thread-id: " + Thread.currentThread().getId());
}
if (ttl == -1) {
get(lockName).deleteAsync();
}
}
```
阅读全文