高级java必会系列一:zookeeper分布式锁

时间:2022-09-02 17:20:05

方案1:
算法思路:利用名称唯一性,加锁操作时,只需要所有客户端一起创建/test/Lock节点,只有一个创建成功,成功者获得锁。解锁时,只需删除/test/Lock节点,其余客户端再次进入竞争创建节点,直到所有客户端都获得锁。
特点:这种方案的正确性和可靠性是ZooKeeper机制保证的,实现简单。缺点是会产生“惊群”效应,假如许多客户端在等待一把锁,当锁释放时候所有客户端都被唤醒,仅仅有一个客户端得到锁。
高级java必会系列一:zookeeper分布式锁
方案2:
算法思路:临时顺序节点实现共享锁
        客户端调用create()方法创建名为“locknode/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。
        客户端调用getChildren(“locknode”)方法来获取所有已经创建的子节点,同时在这个节点上注册上子节点变更通知的Watcher。
        客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点是所有节点中序号最小的,那么就认为这个客户端获得了锁。
        如果在步骤3中发现自己并非是所有子节点中最小的,说明自己还没有获取到锁,就开始等待,直到下次子节点变更通知的时候,再进行子节点的获取,判断是否获取锁。
特点:适合小集群分布式。集群大会耗时严重。

方案3:
算法思路:临时顺序节点实现共享锁的改进实现
    对于加锁操作,可以让所有客户端都去/lock目录下创建临时顺序节点,如果创建的客户端发现自身创建节点序列号是/lock/目录下最小的节点,则获得锁。否则,监视比自己创建节点的序列号小的节点(比自己创建的节点小的最大节点),进入等待。
    对于解锁操作,只需要将自身创建的节点删除即可。
特点:利用临时顺序节点来实现分布式锁机制其实就是一种按照创建顺序排队的实现。这种方案效率高,避免了“惊群”效应,多个客户端共同等待锁,当锁释放时只有一个客户端会被唤醒。

高级java必会系列一:zookeeper分布式锁

开源包menagerie :对方案3的一个封装,直接拿来用,貌似11年以后没更新过------》不建议使用。最新github:https://github.com/sfines/menagerie。

重头戏来了,我们curator包已经封装好了,直接使用即可。-------------》建议使用。具体curator实现原理+测试,后续再分析。