1243.使用 redis 如何设计分布式锁?说一下实现思路?使用 zk 可以吗?如何实现?这两种有什 么区别?

redis:

  1. 线程 A setnx(上锁的对象,超时时的时间戳 t1),如果返回 true,获得锁。
  2. 线程 B 用 get 获取 t1,与当前时间戳比较,判断是是否超时,没超时 false,若超时执行第 3 步;
  3. 计算新的超时时间 t2,使用 getset 命令返回 t3(该值可能其他线程已经修改过),如果t1==t3,获得锁,如果 t1!=t3 说明锁被其他线程获取了。
  4. 获取锁后,处理完业务逻辑,再去判断锁是否超时,如果没超时删除锁,如果已超时,不用处理(防止删除其他线程的锁)。

zk:

  1. 客户端对某个方法加锁时,在 zk 上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点 node1;
  2. 客户端获取该路径下所有已经创建的子节点,如果发现自己创建的 node1 的序号是最小的,就认为这个客户端获得了锁。
  3. 如果发现 node1 不是最小的,则监听比自己创建节点序号小的最大的节点,进入等待。
  4. 获取锁后,处理完逻辑,删除自己创建的 node1 即可。

区别:

zk 性能差一些,开销大,实现简单。