持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
官方文档 已弃用 RedLock
。
8.4. RedLock
This object is deprecated. RLock operations now propagated to all Redis slaves.
关于 RedLock
,有两个大师争论:
Martin Kleppmann
(数据密集型设计,作者):How to do distributed lockingSalvatore
(Redis
作者):Is Redlock safe?
那为什么要学习这个?
学习其思考过程。
RedLock
算法原理
场景:有一个 Redis Cluster
,有 3个 Redis Master
实例。
获取一把分布式锁步骤如下:
- 获取当前时间戳,单位是毫秒
- 轮流尝试在每个
Master
节点上创建锁 - 尝试在大多数节点上建立一个锁,比如 3个节点 就要求是 2个节点(
n / 2 +1
)加上锁 - 客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了
- 要是锁建立失败了,那么就依次删除已经创建的锁
- 只要别人创建了一把分布式锁,你就得不断轮询去尝试获取锁
最核心的一个点:普通的 Redis
分布式锁,其实是在 Redis
集群中根据 hash
算法选择一台 Redis
实例创建一个锁就可以了。
-
hash
算法分配 ,可能容易都指定到同一台Redis
实例上。 -
所以,官方建议手动指定。
这样不用集群也可以喽,只要锁在不同节点上。
举例:创建 3个
Redis
节点(不在同个集群),指定锁到某个节点,这样也是可以的。
说白了,RedLock
算法思想:不能只在一个 Redis
实例上创建锁。
应该是在多个
Redis
实例上创建锁 (n / 2 + 1
),必须在大多数Redis
节点上都成功创建锁,才能算这个整体的RedLock
加锁成功,避免说仅仅在一个Redis
实例上加锁。
Redisson
加锁原理
举个栗子:
@Test
public void test() {
RLock lock1 = redisson.getLock("lock1");
RLock lock2 = redisson.getLock("lock2");
RLock lock3 = redisson.getLock("lock3");
// RedissonRedLock
RLock redLock = redisson.getRedLock(lock1, lock2, lock3);
redLock.lock();
redLock.unlock();
}
RedissonRedLock
锁是 RedissonMultiLock
的一个子类。
RedLock
算法的实现,是依赖于MultiLock
的一个机制来实现的。
public class RedissonRedLock extends RedissonMultiLock {
// 允许锁失败的数量
@Override
protected int failedLocksLimit() {
return locks.size() - minLocksAmount(locks);
}
// 最少锁成功的数量
protected int minLocksAmount(final List<RLock> 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);
}
}
其里面的实现,跟 MultiLock
一致。