分布式锁

 目  录

  1. 分布式的基本原理
  2. Redis实现分布式锁
  3. Zookeeper实现分布式锁
  4. 总结

  1. 分布式锁的基本原理

  分布式锁是分布式系统中实现互斥访问共享资源的一种机制。

  

回到顶端


  2. Redis实现分布式锁

  Redis实现分布式锁的方式有很多种,不同的业务场景也有可能有不同的实现。但所有的实现不管怎么变化,其核心点还是redis的两个命令setNX和expire。

1. SETNX key value
    将 key 的值设为 value ,当且仅当 key 不存在。
    若给定的 key 已经存在,则 SETNX 不做任何动作。
    SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。
  可用版本:
      >= 1.0.0
  时间复杂度:
      O(1)
  返回值:
      设置成功,返回 1 。
      设置失败,返回 0 。

2. EXPIRE key seconds
  为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
  在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。
  可用版本:
    >= 1.0.0
  时间复杂度:
    O(1)
  返回值:
    设置成功返回 1 。
    当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。

3. TTL key
  以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
  可用版本:
    >= 1.0.0
  时间复杂度:
    O(1)
  返回值:
    当 key 不存在时,返回 -2 。
    当 key 存在但没有设置剩余生存时间时,返回 -1 。
    否则,以秒为单位,返回 key 的剩余生存时间。
命令具体含义

  这里主要讲解一种多台机器互作主备的分布式锁实现方式,这种方式源自于团队的一帮技术牛人,几经辗转现在需要我暂时维护这块儿,所以在研究代码的同时对其做一个简单的整理。(图)

  整体思路:task任务通过tryLock本地锁来获得执行权;本地锁由守护线程负责同步redis锁的状态。如下图

    

  具体分为两个部分:

  (1)抢锁/续租:在没有获得锁的时候,不断尝试抢锁;在获得锁之后,不停给redis和本地的锁续租。在应用启动的时候,需要将其注册为守护进程,守护线程每隔几秒运行一次。

  (2)tryLock:判断本地锁是否在续租期,如果是则进行工作,否则什么也不做。由定时task在执行任务之前调用判断。

  抢锁/续租流程如下图:

     

  整体流程如下:

  (1) 应用启动时,注册分布式锁。首先阻塞调用一次抢锁,抢锁之后(不论锁是否抢成功),启动守护线程,每个几秒执行一次抢锁续租。

  (2) 抢锁续租,首先判断本地锁是否已经过期。若已经过期则执行步骤3;若为未过期则执行步骤4。

  (3)尝试setNX抢锁。抢锁成功,设置本地锁有效期时间为当前时间后Xs;若抢锁不成功,则进一步确认redis锁是否是自己,是自己且在TTL大于续租间隔则将redis锁的TTL赋值给本地锁,不是自己则什么也不做。

  (4)尝试expire续租锁,首先读取一下远程锁,判断是否是自己(为了防止极端情况下锁正好过期或者锁被其它节点抢走,需要确认锁是自己拥有的)。如不是则什么也不做;如是则延长redis锁的有效期,延长成功则设置本地锁有效期时间为当前时间后Xs。

  相关代码可参考:Stephan Gao 的 GitHub distributedLock简介

回到顶端


  3. Zookeeper实现分布式锁

待续.......

 

 

 

回到顶端


 参考文章:

 [1] 分布式锁的原理及实现。

 [2] 分布式锁的一点理解。

 [3] Redis命令参考。

  

posted @ 2018-05-05 16:41  葛麻藤蔓  阅读(168)  评论(0编辑  收藏  举报