ZooKeeper 实例 – Leader 选举

Leader 选举用于保证系统的高可用,例如一个重要服务,为防止其出现故障使服务中断,同时准备好另外2个备用,这就需要从3个服务节点中选出一个对外服务,这个服务出现故障后,从另两个服务节点中再选出一个对外提供服务,这个选主过程就是 Leader 选举

Leader 选举是 ZooKeeper 的一个主要应用场景,ZooKeeper 官网也给出了实现思路

实现思路

例如有3个服务,service_node1、service_node2、service_node3

在 ZooKeeper 的根路径下有一个持久节点 /ELECTION

3个服务启动时,都在 /ELECTION 下创建一个名称相同的临时顺序节点 /ELECTION/n_,因为是顺序型节点,ZooKeeper 会自动添加顺序编号

这样,3个服务就和 Zookeeper 中的节点建立起了对应关系

每个服务创建好节点后,获取 /ELECTION 下的所有子节点,看自己是不是编号最小的

sevice_node1 对应的 n_000000 是编号最小的,sevice_node1 成为 Leader

sevice_node2 与 sevice_node3 的编号不是最小的,便监听自己前面的那个节点

sevice_node2 监听 n_000001,sevice_node3 监听 n_000002

当  /ELECTION 下的某个节点被删除时,监听这个节点的服务就会得到通知

例如 service_node1 挂掉了,对应的 n_000000 会自动被删除(因为其是临时节点,创建节点的进程停止后,这个节点会被自动删除)

因为 service_node2 在监控 n_000000 ,n_000000 被删除后,service_node2 就会得到通知

service_node2 会再获取一次 /ELECTION 下的所有子节点 [ n_000002, n_000003 ],发现自己是编号最小的,成为 Leader

那么如果不是 service_node1 挂掉了,而是 service_node2 挂掉了,service_node3 便会得到通知

service_node3 获取 /ELECTION 下的所有子节点 [n_000000, n_000003],发现自己不是编号最小的,就监听排在自己前面的 n_000000

思路总结

所有client都在ZK的固定节点下创建临时顺序节点,然后看自己是不是编号最小的

如果是,成为 leader,否则,监听排在自己前面的节点状态变化

当某个节点被删除时,监听此节点的client获得通知,重新获取一遍所有子节点,看自己是不是编号最小的

如果是,成为 leader,否则,监听排在自己前面的节点状态变化

开源示例

github 上有按照官方思路实现的示例,项目地址

https://github.com/SainTechnologySolutions/allprogrammingtutorials/tree/master/apache-zookeeper/leader-election

其中的 dist 目录下存放了编译好的 jar 包,可以直接运行

运行示例

在3个命令终端下分别执行

java -jar leader-election-0.0.1-SNAPSHOT.jar 1 192.168.31.204:2181

192.168.31.204:2181 是 ZooKeeper 的 IP 和端口号

java -jar leader-election-0.0.1-SNAPSHOT.jar 2 192.168.31.204:2181

java -jar leader-election-0.0.1-SNAPSHOT.jar 3 192.168.31.204:2181

关掉终端 1,看终端 2 的反应,2 收到了 1 的删除事件,自己变成了编号最小的,成为新的 Leader

还有另一个实现示例,可以一起参考

https://github.com/perezrathke/zookeeper-leader-election

 


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。