一、Zookeeper选举概念
1、Zookeeper节点角色
1)Leader
- 集群中有且仅有一个Leader,通过选举产生
- 事务请求的唯一调度者和处理者,保证集群事务处理的顺序性
- 集群内部服务器的调度者
2)Follower
- 处理客户端非事务请求,转发事务请求给Leader服务器
- 参与事务请求Proposal的投票
- 参与Leader选举的投票
3)Observer
- 处理客户端非事务请求,转发事务请求给Leader服务器
- 不参加任何形式的投票,包括选举和事务投票(超过半数确认)
- Obersver的存在是为了提高Zookeeper对外提供读能力的性能
2、Zookeeper节点状态
- Looking:寻找Leader状态,处于该状态需要进入选举流程
- Leading:领导者状态,处于该状态的节点说明角色已经是Leader
- Following:跟随状态,表示Leader已经选举出来了,当前节点的角色是Follower
- Observing:观察状态,表示当前节点的角色是Observer
3、事务ID
Zookeeper状态的每次变化都会接收一个zxid(Zookeeper事务ID)形式的标记,zxid是一个64位的数字,高32位表示该事务发生的集群选举周期(集群每发生一次Leader选举,值加1),低32位表示该事务在当前选举周期内的递增次序(Leader每处理一个事务请求,值加1,发生一次Leader选举,低32位要清零),由Leader统一分配,全局唯一,不断递增。
ZXID展示了所有Zookeeper状态的变更顺序,每次变更都会有一个唯一的zxid,如果zxid1小于zxid2说明zxid1在zxid2之前发生。
二、Zookeeper选举流程
Zookeeper Leader选举是保证分布式数据一致性的关键所在,Leader选举分为以下两种情况:
- Zookeeper集群初始化启动时选举
- Zookeeper集群运行期间Leader重新选举
1、Zookeeper集群初始化启动时选举
按照前文介绍,Zookeeper集群一般由奇数个节点组成,此处以3台服务器节点(ZK1,ZK2,ZK3)组成的Zookeeper集群为例。
在集群初始化阶段,当一个节点ZK1启动时,其单独无法进行和完成Leader选举的,当第二个节点ZK2启动时,此时两个节点可以相互通信,每个节点都试图找到Leader,于是进入Leader选举流程。选举流程如下:
1)发出投票
初始化阶段,ZK1和ZK2都将自己作为Leader来进行投票,每次投票会包含所推举的节点的myid和zxid,使用(myid,zxid)来表示,此时ZK1的投票为(1,0),ZK2的投票为(2,0),然后各自将这个投票发给集群中的其他机器。
2)接收投票
集群中的每个服务器接收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自Looking状态的服务器等。
3)处理投票
针对每一个投票,服务器都要将别人的投票和自己的投票进行比较,规则如下:
- 优先检查zxid,zxid比较大的服务器优先作为Leader
- 如果zxid相同,那么久比较myid,myid较大的服务器作为Leader
在本案例中,ZK1的投票是(1,0),接收ZK2的投票为(2,0),首先比较两者的zxid都为0,再比较myid,ZK2的myid大,所以ZK2胜。ZK1更新自己的投票为(2,0),然后重新投票。对于ZK2无需更新投票,只是再次向集群中的所有服务器发送上一次的投票即可。
4)统计投票
每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受了相同的投票信息。对于ZK1、ZK2而言,都统计出集群中已经有两台机器接受了(2,0)的投票信息,此时便可以认为已经选出ZK2作为Leader。
5)改变节点状态
一旦确定Leader,每个服务器就会更新自己的状态。如果是Leader,就变更为Leading,如果是Follower,那么久变更为Following。当新的节点ZK3启动时,发现已经有Leader了,不再选举,直接将状态从Looking改为Following。
2、Zookeeper集群运行期间Leader重新选举
在Zookeeper运行期间,如果Leader节点挂掉了,那么整个Zookeeper集群将暂停对外服务,进入新一轮的Leader选举。同样以3台服务器节点(ZK1,ZK2,ZK3)组成的Zookeeper集群为例,当前Leader是ZK2,某一时刻ZK2挂掉了,此时便开始重新选举Leader,选举流程如下:
1)变更状态
当Leader节点挂掉后,剩余的非Observer节点服务器会将自己的状态变更为Looking,然后进入Leader选举流程。
2)发出投票
在运行期间,每个服务器上的zxid可能不同,此时假定ZK1的zxid为124,ZK3的zxid为123。
在第一轮投票中,ZK1和ZK3都会投自己,产生投票(1,124)和(3,123),然后将投票发送给集群中的所有服务器。
3)接收投票
和启动时过程相同。
4)处理投票
和启动时过程相同,由于ZK1的zxid大,所以ZK1将会成为Leader。
5)统计投票
和启动时过程相同。
6)改变节点状态
和启动时过程相同。