点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。
文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。
说说zk的选举机制
基础概念
- zxid=事务id=一个时间戳,代表当前事件发生的先后顺序,zxid越小代表事件发生的时间越早;zxid由64位数字组成=高32位的epoch+低32位递增数列,每个leader都有自己的统治年代,高32位epoch代表当前leader的统治年,低32位则是递增计数位,所以在同一个集群中每个节点的zxid都都可能不同,因为高32位epoch相同但低32位递增数列不同;
myid=zk集群中每个节点的标识id; - zk的leader选举分为集群启动阶段和运行阶段的选举
- 选举原则:比较每个节点的(zxid,myid),在当选节点的票数>总节点数/2(该原则可以避免zk集群的脑裂问题),zxid大者当选,若zxid相同再比较myid,myid大者当选;若当前已发生投票节点数未过半,则继续等待投票
- zk保证CAP中的CP,不保证可用性(A):因为在zk集群选举过程中不对外提供服务
- zk可以保证数据不丢失:因为在选举过程中zxid较大的节点会当选leader,zxid越大代表数据越新(但这种保证是不严格的:启动阶段zxid相同,但运行阶段zxid相对较大的位于中间的节点会当选,zxid最大但位于最后的节点反而不当选)
- 选举需满足【当选节点的票数>总节点数/2】,故这种情况选举不出leader:整个集群中过半的节点挂掉了,此时永远不满足【当选节点的票数>总节点数/2】
- 集群总节点数一般设为基数【2N+1】,目的有两个:
- 出于成本考虑。当集群有5个节点时,最多挂掉2个节点,此时剩下3台,最大的当选节点票数为3>总节点数/2=5/2=2.5;当集群有6个节点,最多挂掉2个节点,此时剩下4台,最大当选票数为4>总节点数/2=6/2=3。所以5个节点和6个节点服务器的容错数都是一样的,但明显5台服务器成本更少。
- 防止脑裂。脑裂=一个集群由于网络故障分为两个集群,这两个集群又各自选选举出了自己的主节点,这样就有两个主节点了,原本只有一个主节点现在有了两个,类似于大脑裂开了两半;当考虑过半机制时,不管节点裂开成多少个集群,每个集群都需要超过总节点数的一半才能选主成功,这样自始至终都只有一个裂开后形成的集群能正常选主,其他裂开后形成的集群不能选主而不能正常工作
启动阶段的leader选举
zk集群至少要有3个节点,假如有5个节点1、2、3、4、5先后启动,它们启动时的zxid都是一样的(设为0):
->节点1进入looking选举状态,给自己投票,发出(0,1),此时当选节点票数=1<节点总数的一半=2.5,故节点1仍保持looking状态继续等待选举
->节点2进入looking选举状态,给自己投票,发出(0,2),myid为2最大,2当选,但此时当选节点票数=2<节点总数的一半=2.5,故节点2仍保持looking状态继续等待选举
->节点3进入looking选举状态,给自己投票,发出(0,3),myid为3最大,3当选,且此时当选节点票数=3>节点总数的一半=2.5,故节点3当选leader
->节点4进入looking选举状态,给自己投票,发出(0,4),但此时集群leader已选出,所以节点4仍成为follwer
->节点5进入looking选举状态,给自己投票,发出(0,5),但此时集群leader已选出,所以节点5仍成为follwer
->选举完成后,leader的状态由looking变为leading,follower的状态由looking变为following
总的来说,启动阶段的选举当选的必然为位于中间的节点
运行阶段的选举
运行阶段每个节点的zxid都可能不同,但选举原则与启动阶段一样,都是先比较zxid,再比较myid,假如主节点3运行中挂掉了,其他所有从节点全部进入looking状态,节点1、2、4、5的zxid为121、122、124、125,且各从节点都推举自己为下一个leader,节点1发出(121,1),节点2发出(122,2),节点4发出(124,4),由于节点4的zxid比1、2的大,故4当选,且当选节点票数=3>总节点数/2=5/2=2.5,所以4当选新一代leader,节点5发出(125,5),但此时已经选举出leader,所以5成为follwer,最后leader变更状态为leading,follower变更为following
OK,如果文章哪里有错误或不足,欢迎各位留言。
创作不易,各位的「三连」是二少创作的最大动力!我们下期见!
|