前言
联合锁和红锁放在一起来分析,是因为这两种锁实现在Redisson中,关联密切。
/**
* Returns MultiLock instance associated with specified locks
*
* @param locks - collection of locks
* @return MultiLock object
*/
RLock getMultiLock(RLock... locks);
/*
* Use getLock method instead. Returned instance uses Redis Slave synchronization
*/
@Deprecated
RLock getRedLock(RLock... locks);
红锁
上面getRedLock方法上有@Deprecated注解,说明在Redisson实现中,不推荐使用红锁。
简介
红锁是官方提出的一个锁方案,大概如下:
假设redis集群有5个节点,一个客户端申请锁时,会向所有的节点申请锁,只有大于一半的节点数量返回成功,且耗费的总时间小于锁有效时间,才会判定为拿锁成功,否则会被认定为失败,需要将已经成功的节点锁释放掉。
具体官方文档见:redis.io/topics/dist…
实现
RedissonRedLock继承了联合锁【RedissonMultiLock】,也没有重写核心方法。
/**
* RedLock locking algorithm implementation for multiple locks.
* It manages all locks as one.
*
* @see http://redis.io/topics/distlock
*
* @author Nikita Koksharov
*
*/
public class RedissonRedLock extends RedissonMultiLock {
/**
* Creates instance with multiple {@link RLock} objects.
* Each RLock object could be created by own Redisson instance.
*
* @param locks - array of locks
*/
public RedissonRedLock(RLock... locks) {
super(locks);
}
@Override
protected int failedLocksLimit() {
return locks.size() - minLocksAmount(locks);
}
protected int minLocksAmount(final List locks) {
return locks.size()/2 + 1;
}
@Override
protected long calcLockWaitTime(long remainTime) {
return Math.max(remainTime / locks.size(), 1);
}
@Override
public void unlock() {
unlockInner(locks);
}
}
联合锁
Groups multiple independent locks and manages them as one lock.
是对一个锁的集合进行操作,与红锁不同的是,集合中所有的锁,要么全部拿锁成功,要么失败,不存在部分成功。实现类:RedissonMultiLock
获取锁
不限等待时间获取
lock
@Override
public void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException {
long baseWaitTime = locks.size() * 1500;
long waitTime = -1;
if (leaseTime == -1) {
waitTime = baseWaitTime;
} else {
leaseTime = unit.toMillis(leaseTime);
waitTime = leaseTime;
if (waitTime {
failedLocksLimit = failedLocksLimit();
acquiredLocks.clear();
// reset iterator
while (iterator.hasPrevious()) {
iterator.previous();
}
checkRemainTimeAsync(iterator, result);
});
return;
} else {
failedLocksLimit--;
}
}
// 如果持有时间不限制,则直接再次调用此方法,操作下一个锁;否则判断持有时间是否已经耗尽,如果时间耗尽,则解锁,并返回拿锁失败
checkRemainTimeAsync(iterator, result);
});
}
执行步骤:
释放锁
联合锁不支持强制释放
同步无返回
联合锁释放时,阻塞执行,直到释放完成以后,才返回。
@Override
public void unlock() {
List futures = new ArrayList(locks.size());
for (RLock lock : locks) {
// 拿到每个锁释放的Future结果
futures.add(lock.unlockAsync());
}
for (RFuture future : futures) {
// 遍历等待每个锁释放完成
future.syncUninterruptibly();
}
}
异步有返回
将参数中的锁逐个释放,直接返回一个Future。
protected RFuture unlockInnerAsync(Collection locks, long threadId) {
if (locks.isEmpty()) {
return RedissonPromise.newSucceededFuture(null);
}
RPromise result = new RedissonPromise();
AtomicInteger counter = new AtomicInteger(locks.size());
for (RLock lock : locks) {
lock.unlockAsync(threadId).onComplete((res, e) -> {
// 如果释放锁的过程中,发生异常,则直接返回错误。
if (e != null) {
result.tryFailure(e);
return;
}
// 当锁全部释放之后,返回成功
if (counter.decrementAndGet() == 0) {
result.trySuccess(null);
}
});
}
return result;
}
强制释放
联合锁不支持强制释放,重写的方法内直接返回异常
@Override
public boolean forceUnlock() {
throw new UnsupportedOperationException();
}