RedissonLock 分布式锁

  1. 普通的分布式锁实现 依靠简单的lua脚本;但是缺点是redis单点故障问题无法解决;如果主从架构也无法保证主挂了之前主从是完全同步的
  2. 执行时间超过了锁的过期时间;需要启动一个看门狗定时器,再不停的续期;以保证当前线程未处理完成之前不会导致分布式锁失效
  3. 为了解决redis单点故障问题,这里引入了redissionLock;依赖几个没有任何主从关系的redis节点
  4. Redlock的实现如下:
    1、获取当前时间
    
    2、依次获取N个节点的锁。每个节点加锁的实现方式同上。这里有个细节,就是每次获取锁的时候的过期时间都不同,需要减去之前获取锁的操作的耗时:
        比如传入的锁的过期时间为500ms;
        获取第一个节点的锁花了1ms,那么第一个节点的锁的过期时间就是499ms;
        获取第二个节点的锁花了2ms,那么第二个节点的锁的过期时间就是497ms;
        如果锁的过期时间小于等于0了,说明整个获取锁的操作超时了,整个操作失败。
    
    3、判断是否获取锁成功。如果client在上述步骤中获取到了(N/2 + 1)个节点锁,并且每个锁的过期时间都是大于0的,则获取锁成功,否则失败。失败时释放锁。
    
    4、失败的话,需要删除所以节点的锁记录; 获取失败的节点也需要同步删除操作,因为防止网络抖动引起的响应超时
    
    

     

  5.  分布式锁的坑
    1、性能问题
       1)获取锁的时间上。如果redlock运用在高并发的场景下,存在N个master节点,一个一个去请求,耗时会比较长,从而影响性能。但是可以并行处理的,不过还是得预估好获取锁的时间,保证锁的TTL > 获取锁的时间+任务处理时间
       2)红锁肯定更加耗用资源,以及降低并发量;  可以通过分段锁的思想降低锁的粒度;提高并发量
          考虑批量加锁的场景,批量加锁防止并发操作形成无法加锁成功
    
    2、重试的问题  多个client同时需要获取相同的分布式锁;这时就很大程度会导致,每个client都获取了部分节点锁,但是又都没有获取半数以上的情况;导致获取失败;失败后重试,这个重试的时间间隔最好随机化一点,这样可以获取成功的机会大大增加
    
    3、节点宕机 
       比如redis节点有 A B C D  E 五个节点
       系统甲获取 ABC三个节点成功了;但此时C挂了
       系统乙获取 DE成功了;此时C重启成功了  这样系统乙 CDE三个节点成功了
       导致 多个系统都获取分布式锁成功了
       
       解决方案:延迟重启(锁失效后再次重启)    或者增加节点数量
    
    4、任务执行时间超过锁的TTL
    
    Client1获取到锁;
    Client1开始任务,然后发生了STW的GC,时间超过了锁的过期时间;
    Client2 获取到锁,开始了任务;
    Client1的GC结束,继续任务,这个时候Client1和Client2都认为自己获取了锁,都会处理任务,从而发生错误。
    
    解决方案 一种解决方案是不设置TTL,而是在获取锁成功后,给锁加一个watchdog,watchdog会起一个定时任务,在锁没有被释放且快要过期的时候会续期
    
    
    5、系统时钟漂移
    

你可能感兴趣的:(分布式锁)