Redisson的加锁方法有两个,tryLock和lock,使用上的区别在于tryLock可以设置锁的过期时长leaseTime和等待时长waitTime,核心处理的逻辑都差不多
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long time = (waitTime);
long current = ();
long threadId = ().getId();
// 尝试获取锁,如果没取到锁,则返回锁的剩余超时时间
Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
// lock acquired
// ttl为null,说明可以抢到锁了,返回true
if (ttl == null) {
return true;
}
// 如果waitTime已经超时了,就返回false,代表申请锁失败
time -= () - current;
if (time <= 0) {
acquireFailed(waitTime, unit, threadId);
return false;
}
current = ();
/**
订阅锁释放事件,并通过 await 方法阻塞等待锁释放,有效的解决了无效的锁申请浪费资源的问题:
基于信息量,当锁被其它资源占用时,当前线程通过 Redis 的 channel 订阅锁的释放事件
一旦锁释放会发消息通知待等待的线程进行竞争.
*/
RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
if (!(time, )) {
if (!(false)) {
((res, e) -> {
if (e == null) {
unsubscribe(subscribeFuture, threadId);
}
});
}
acquireFailed(waitTime, unit, threadId);
return false;
}
try {
//如果获取锁的耗时超过最大等待时间,加锁失败
time -= () - current;
if (time <= 0) {
acquireFailed(waitTime, unit, threadId);
return false;
}
//在最大等待时间内循环获取锁
while (true) {
long currentTime = ();
ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {
return true;
}
time -= () - currentTime;
if (time <= 0) {
acquireFailed(waitTime, unit, threadId);
return false;
}
// waiting for message
currentTime = ();
// waiting for message,等待解锁消息
if (ttl >= 0 && ttl < time) {
().getLatch().tryAcquire(ttl, );
} else {
().getLatch().tryAcquire(time, );
}
time -= () - currentTime;
if (time <= 0) {
acquireFailed(waitTime, unit, threadId);
return false;
}
}
} finally {
//取消订阅消息
unsubscribe(subscribeFuture, threadId);
}
// return get(tryLockAsync(waitTime, leaseTime, unit));
}
Redission分布式锁原理_知知之之的博客-****博客_redission实现分布式锁原理原理源码中加锁lua代码if (('exists', KEYS[1]) == 0) then ('hset', KEYS[1], ARGV[2], 1); ('pexpire', KEYS[1], ARGV[1]); return nil; end;if (('hexists', KEYS[1], ARGV[2]) == 1) thenhttps:///weixin_35973945/article/details/124151830
需要特别注意的是,RedissonLock 同样没有解决 节点挂掉的时候,存在丢失锁的风险的问题。而现实情况是有一些场景无法容忍的,所以 Redisson 提供了实现了redlock算法的 RedissonRedLock,RedissonRedLock 真正解决了单点失败的问题,代价是需要额外的为 RedissonRedLock 搭建Redis环境。
所以,如果业务场景可以容忍这种小概率的错误,则推荐使用 RedissonLock, 如果无法容忍,则推荐使用 RedissonRedLock。