Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

请注意,此篇文章并不是介绍Zookeeper集群内部Leader的选举机制,而是应用程序使用Zookeeper作为选举。

使用Zookeeper进行选举,主要用到了Znode的两个性质:

  1. 临时节点(EPHEMERAL)
  2. 序列化节点(SEQUENCE)

每一个临时的序列化节点代表着一个客户端(client),也就是选民。主要的设计思路如下:

首先,创建一个选举的节点,我们叫做/election。 然后,每有一个客户端加入,就创建一个子节点/election/n_xxx,这个节点是EPHEMERAL并且SEQUENCE,xxx就是序列化产生的单调递增的数字。 在所有子节点中,序列数字做小的被选举成Leader。

上面的并不是重点,重点是Leader失败的检测,Leader失败后,一个新的客户端(client)将被选举成Leader。实现这个过程的一个最简单的方式是 所有的客户端(client)都监听Leader节点,一旦Leader节点消失,将通知所有的客户端(client)执行Leader选举过程,序列数字最小的将被选举成Leader。 这样实现看似没有问题,但是当客户端(client)数量非常庞大时,所有客户端(client)都将在/election节点执行getChildren(),这对Zookeeper 的压力是非常大的。为了避免这种“惊群效应”,我们可以让客户端只监听它前一个节点(所有序列数字比当前节点小,并且是其中最大的那个节点)。 这样,Leader节点消失后,哪个节点收到了通知,哪个节点就变成Leader,因为所有节点中,没有比它序列更小的节点了。

具体步骤如下:

  1. 使用EPHEMERAL和SEQUENCE创建节点/election/n_xxx,我们叫做z。
  2. C为/election的子节点集合,i是z的序列数字。
  3. 监听/election/n_j,j是C中小于i的最大数字。

接收到节点消失的事件后:

  1. C为新的/election的子节点集合
  2. 如果z是集合中最小的节点,则z被选举成Leader
  3. 如果z不是最小节点,则继续监听/election/n_j,j是C中小于i的最大数字。

具体代码如下:

Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

Zookeeper应用之——选举(Election)

我们将启动5个线程作为参选者,模拟每一个Leader死去,并重新选举的过程。启动程序如下:

Zookeeper应用之——选举(Election)

运行结果如下:

Zookeeper应用之——选举(Election)

Zookeeper作为选举的应用就介绍完了,项目示例请参考:https://github.com/liubo-tech/zookeeper-application。


分享到:


相關文章: