• 全部文章 专栏目录
  • 互动问答
  • 栈栈作者
    2019-08-26 17:23:00
    Zookeeper共享锁的【羊群效应】

    Zookeeper的一大应用就是分布式锁,分布式锁在集群中的应用是很普遍的,它可以促进资源的合理分配,防止顺序错乱。

    分布式锁有分为排它锁和共享锁。

    回归正题,这里主要讲共享锁机制会出现的羊群效应。

    一般共享锁的实现逻辑

    zookeeper中节点的创建类型有4类,这里我们重点关注下临时顺序节点。这种类型的节点有几下几个特性:

    1. 节点的生命周期和客户端会话绑定,即创建节点的客户端会话一旦失效,那么这个节点也会被清除。

    2. 每个父节点都会负责维护其子节点创建的先后顺序,并且如果创建的是顺序节点(SEQUENTIAL)的话,父节点会自动为这个节点分配一个整形数值,以后缀的形式自动追加到节点名中,作为这个节点终的节点名。

    利用上面这两个特性,我们来看下获取实现分布式锁的基本逻辑:

    1. 客户端调用create()方法创建名为“_locknode_/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。

    2. 客户端调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,同时在这个节点上注册上子节点变更通知的Watcher。

    3. 客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点是所有节点中序号小的,那么就认为这个客户端获得了锁。

    4. 如果在步骤3中发现自己并非是所有子节点中小的,说明自己还没有获取到锁,就开始等待,直到下次子节点变更通知的时候,再进行子节点的获取,判断是否获取锁。

    羊群效应

    上面这个分布式锁的实现中,大体能够满足了一般的分布式集群竞争锁的需求。这里说的一般性场景是指集群规模不大,一般在10台机器以内。

    不过,细想上面的实现逻辑,我们很容易会发现一个问题,步骤4,“即获取所有的子点,判断自己创建的节点是否已经是序号小的节点”,这个过程,在整个分布式锁的竞争过程中,大量重复运行,并且绝大多数的运行结果都是判断出自己并非是序号小的节点,从而继续等待下一次通知——这个显然看起来不怎么科学。客户端无端的接受到过多的和自己不相关的事件通知,这如果在集群规模大的时候,会对Server造成很大的性能影响,并且如果一旦同一时间有多个节点的客户端断开连接,这个时候,服务器就会像其余客户端发送大量的事件通知——这就是所谓的羊群效应。而这个问题的根源在于,没有找准客户端真正的关注点。

    我们再来回顾一下上面的分布式锁竞争过程,它的核心逻辑在于:判断自己是否是所有节点中序号小的。于是,很容易可以联想的到的是,每个节点的创建者只需要关注比自己序号小的那个节点。

    改进后的共享锁逻辑

    下面是改进后的分布式锁实现,和之前的实现方式不同之处在于,这里设计成每个锁竞争者,只需要关注”_locknode_”节点下序号比自己小的那个节点是否存在即可。实现如下:

    1. 客户端调用create()方法创建名为“_locknode_/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。

    2. 客户端调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,注意,这里不注册任何Watcher。

    3. 客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点序号小,那么就认为这个客户端获得了锁。

    4. 如果在步骤3中发现自己并非所有子节点中小的,说明自己还没有获取到锁。此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时注册事件监听。

    5. 之后当这个被关注的节点被移除了,客户端会收到相应的通知。这个时候客户端需要再次调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,确保自己确实是小的节点了,然后进入步骤3。

    2
    2
    ZooKeeper要点分析
    创建时间:2019-08-26 17:20:10
    从协议到应用,一步步讲解zookeeper在大数据系统中的应用,主要是一些要点分析
    展开
    订阅须知

    • 所有用户可根据关注领域订阅专区或所有专区

    • 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

    • 专区发布评论属默认订阅所评论专区(除付费小栈外)

    作者

    • 栈栈
      作者
    戳我,来吐槽~