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
如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。