一、ZK的leader选举
1. zk集群中三种类型的节点与节点状态
节点介绍
- Observer节点: 它只是为了提升读性能,并不会参与任何决策过程,就算它挂了,也不影响
- Follower节点: 少数节点挂了,没超过半数,没影响,超过半数需要把节点恢复才能运行
- Leader节点: leader在整个集群具有至关重要的作用,整个集群的协调都是它发起的,挂掉,整个集群没法运行,需要选举
节点状态
- looking:节点处于选举状态
- following:当前节点是跟随者,服从 leader 节点的命令,后面它是会参与投票的
- Obsering:观察状态,同步leader状态,但是不参与投票
- leading:当前节点是 leader,负责协调事务
2. leader选举过程
对于zk集群来讲,有两种情况会发生leader选举
- 集群启动期间leader选举
- 集群运行期间leader选举
整个leader选举的过程就是投票的过程,当某一个节点收到超过半数节点的选票的话,就可以认为它当选leader。
具体在选举中,决定投票给谁,会根据两个重要的ID来判断:
- 事务ID(zxid),哪个服务器上的事务ID最大,就投给哪个(对应场景:Leader故障,事务型请求已提交)
- 当两个节点事务ID一样的话,就会看节点编号,也就是myid里面存的编号,哪个大投给哪个
但是在选举的时候,可能不止一轮的投票。在zk里面,有个轮次的概念,就是每一次头片它其实是有时间限制的【syncLimit:集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)】。如果当前投出去的票,没有收到反馈,那么在等待一段时间后,就当作超时处理,这个时间就可以发起下一轮的投票,但是也有可能,上一轮的反馈它是因为网络延迟的问题,这个时候才收到,那么因为现在已经是开始下一轮了,所以这个也只能当作无效票处理了。
选举算法
-
首先每个节点均发起选举自己为领导者的投票(自己的投给自己);因为刚开始也不知道哪个节点的事务ID最大,所以就先给自己一票再说,接着就给其它节点发消息来拉票,拉票的时候,像在选举的时候一样,拉票的时候就会说自己能力多牛,那么这里也一样,它会把当前节点上最大的事务ID给带过去
-
其它节点收到拉票请求时,就会比较发起者的事务ID,是否比自己最新的事务ID大,如果比自己的ID大,那好就给它投一票吧,否则就不投给它了。那如果事务ID相等的话,则比较发起者的服务器编号。这一点呢我们前面也说到过,就像选举的时候,先看一下能力谁强,再看一下谁的年纪大。
-
然后经过每一轮的投票之后,就看有没有哪个节点,它获得的票数(含自己的)大于集群的半数,有的话就说明这个节点竞选成功,成为了Leader节点,未超过半数且领导者未选出,则再次发起投票。
3. 集群启动期间leader选举
- 每个节点启动的时候,节点状态为Looking, 给自己投票
- 接下里的节点对比服务id,依次滚动,直到有超过半数投票,当选为leader
- 服务4启动的时候,直接改为following状态
4. 集群故障期间leader选举
运行期间选举与初始状态选举基本类似,大致分为几个步骤
-
状态变更。Leader故障后,剩下的follower节点应为跟leader联系不上,这时候会把自己的服务状态变更为looking,然后开始进入leader选举过程
-
每个server会发出投票
-
接收来自各个服务器的投票,如果其他服务器的数据比自己的新会改投票
-
处理和统计投票,每一轮投票结束后会统计投票,超过半数即可当选
-
改变服务器的状态,宣布当选