【Redisson】RedLock 锁源码剖析

732 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

官方文档 已弃用 RedLock

8.4. RedLock
This object is deprecated. RLock operations now propagated to all Redis slaves.

关于 RedLock ,有两个大师争论:

那为什么要学习这个?

学习其思考过程。

RedLock 算法原理

场景:有一个 Redis Cluster,有 3个 Redis Master 实例。

获取一把分布式锁步骤如下:

  1. 获取当前时间戳,单位是毫秒
  2. 轮流尝试在每个 Master 节点上创建锁
  3. 尝试在大多数节点上建立一个锁,比如 3个节点 就要求是 2个节点(n / 2 +1)加上锁
  4. 客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了
  5. 要是锁建立失败了,那么就依次删除已经创建的锁
  6. 只要别人创建了一把分布式锁,你就得不断轮询去尝试获取锁

2022-06-2111-07-27.png

最核心的一个点:普通的 Redis 分布式锁,其实是在 Redis 集群中根据 hash 算法选择一台 Redis 实例创建一个锁就可以了。

  • hash算法分配 ,可能容易都指定到同一台 Redis 实例上。

  • 所以,官方建议手动指定。

    这样不用集群也可以喽,只要锁在不同节点上。

    举例:创建 3个 Redis 节点(不在同个集群),指定锁到某个节点,这样也是可以的。

2022-06-2111-16-22.png

说白了,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 一致。