ZooKeeper集群Leader选举理论解读(初次选举和故障恢复)
首发CSDN:徐同学呀,原创不易,转载请注明源链接。我是徐同学,用心输出高质量文章,希望对你有所帮助。
一、前言
ZooKeeper
参考 Paxos
算法,专门设计了一种支持崩溃恢复的原子广播协议 Zab
(Zookeeper Atomic Broadcast
),Leader
选举是其核心思想,也是保证ZooKeeper
数据一致性的关键所在。
二、基本概念
1、服务器角色
一个正常运行的zk集群中,一定存在两种服务器角色 Leader
和 Follower
,Leader
负责事务请求处理协调和数据同步以保证数据顺序最终一致性;Follower
具有投票,只读请求可以自己处理,但是事务请求需要转发给Leader
。还有一种角色 Observer
,和 Follower
统称为 Learner
,但是没有投票权,也不参与过半数机制。
2、票据ZXID和myid
在进行Leader
选举时,ZXID
和myid
作为投票依据,比较服务之间ZXID
和myid
的大小来判定票投给谁,最终得票过半数的成为Leader
。
(1)ZXID
ZXID
是事务ID,由Leader
生成,是一个16进制的递增数字,共64位(二进制),由两部分组成:高32位代表当前Leader
任期编号,每进行一次Leader
选举就加一;低32位是事务计数器,递增,整体上是递增的。
ZXID
的作用主要有两个:
- 保证数据的顺序一致性,所有事务请求统一由
Leader
发起提议,严格按ZXID
顺序执行,当前事务请求没有处理完,再来新的事务请求就会阻塞。 ZXID
参与选票依据,ZXID
大的获得选票。
(1)myid
myid
应该比较眼熟吧,在搭建zk集群时,每个服务节点的 dataDir
目录下都会创建一个myid
文件,文件中只包含一个数字,且不能重复;在zoo.cfg
配置里也可以看到有几行server.A=B:C:D
,A代表的就是myid
。
myid
作为zk
服务的ServerId
,简称SID
,并且也是选票依据,当ZXID
相等时,myid
大的获得选票。
三、Leader选举
1、集群第一次启动Leader选举
因为3个服务节点的zk集群Leader
选举可能过于简单,所以下面以5个服务节点组成的zk集群来看看Leader
选举的过程。
第一次启动,都处于初始状态,ZXID
都是0,myid
分别为1、2、3、4、5。票据(ZXID,myid)
分别为(0,1)
、(0,2)
、(0,3)
、(0,4)
、(0,5)
(此概念不涉及源码层面,但是原理上差不多),如下是具体的投票选举过程:
myid=1
的服务器启动,发起一次投票,服务器1给自己投1票,票数不过半,选举无法完成。myid=2
的服务器启动,再发起一次投票,服务器1和服务器2分别给自己投一票。- 服务器1和服务器2交换选票信息,先比较
ZXID
,都是0,再 比较myid
,服务器2的myid
比服务器1大,所以服务器1的票据更改为(0,2)
,服务器2不需要更改。 - 统计选票,服务器1和服务器2变更选票信息后再次交换选票,服务器1和服务器2都有两张一样的票
(0,2)
,意为服务器2有两票,但是票数不过半,无法完成投票。 myid=3
的服务器启动,发起投票,此时服务器1和2持有的票据都是(0,2)
,服务器3的票据为(0,3)
,互相交换选票(每个服务器的票据都要广播给其他具有投票权的服务器),服务器3的myid
比服务器2的 大,服务器1和2变更票据为(0,3)
,服务器3保持不变。- 再次统计选票,服务器3有三张票,服务器1和2都是零票。服务器3持有的票数过半,
Leader
选举完成,服务器3成为Leader
,服务器1和2成为Follower
。 myid=4
的服务器启动,发现集群中已经有Leader
了,就变更自己的角色状态为Follower
。myid=5
的服务器启动,同理也变更自己的角色状态为Follower
。
过程还是比较简单,也很容易理解,对投票过程总结3点:
- 交换选票,每个服务器将自己持有的票据广播给其他具有投票权的服务器。
- 变更选票,票据比较,所有服务器都将自己的选票信息更新为那个
ZXID
最大的或者myid
最大的服务器的选票,这就相当于投票了。 - 统计选票,每个服务器再广播一次自己持有的票据,每个服务器判断自己接收到的相同票据数量是否过半数,是就推选该票据的
myid
对应的服务器成为Leader
,其他都为Follower
。
如下图是伪集群服务器数量3的第一次启动过程演示:
2、集群运行期间Leader选举
zk集群正常运行期间,一旦选出了Leader,那么所有服务器的角色都不会再发生变化。后启动的服务器发现有Leader
,就直接变更自己的角色为Follower
;Follower
挂了,只要正常运行的服务器数量还在半数以上,整个集群就还可以正常对外提供服务。
但是一旦Leader
所在的服务器挂了,如果集群中正常运行的机器半数以上,就得重选Leader
。
(1)Leader故障的几种典型场景
Leader
在挂掉的时候,可能还有一些写操作没有完成,可能会造成剩下的服务器数据不一致。如下是几种Leader
故障的场景:
Leader
完成了所有事务COMMIT
,然后挂了,此时过半数以上的服务器的数据是一致的,重选Leader
基本不影响。Leader
在接收到事务请求至最后广播COMMIT
之前的某个时刻挂了,这都属于未完成的事务请求,即使有服务器已经把事务请求持久化到了日志文件,但是还没有完成最后的COMMIT
将数据同步到内存数据库。未完成的事务会被丢弃。Leader
在广播COMMIT
的过程中挂了,这就导致某些收到了COMMIT
完成了事务,有些没收到,还处于持久化事务日志文件的阶段,最终导致数据不一致。
(2)故障恢复
故障恢复包括两部分:Leader
选举和数据恢复。
Leader
重新选举的过程和第一次启动选举一样,不再赘述。成为新Leader必须满足以下两个条件:
- 新
Leader
的ZXID
是所有服务器中最大的,这就可以最大限度的恢复数据。 - 新
Leader
不能包含未COMMIT
的事务提议,如果事务日志文件中有未同步到内存数据库的事务将会回滚丢弃。
新Leader选举出来以后,就开始恢复数据了。为了集群全局数据一致性,所有的 Follower
上的数据都必须和Leader的一样:
Leader
有的Follower
没有,Leader
将这些事务同步给Follower
。Leader
没有的,Follower
有,Follower
需要回滚丢弃这些所谓超前的事务。
注:如果原先集群运行了一段时间,产生了数据不一致,然后全部停机后,再一个个重启,最好是先去看看每个服务的事务日志文件内记录的最后提交的ZXID
,最大的那个服务先重启,否则可能会导致Leader
已经选举好了,后面一个带着最全数据的服务节点重启了,反而要回滚事务。
需要注意的是在Leader选举的过程中,集群是处于无法正常对外提供服务的状态。
3、Observer旁观者的好处
在Leader
选举的过程中一直没有说Observer
,原因是Observer
没有投票权,但是它除了没有投票权,不参与过半机制外,和Follower
差不多,也可以通过客户端连接,也可以从Leader
同步数据。
Observer
的机制可以应用在扩容上,不仅可以实现数据的动态迁移和扩容,还可以就只作为一个与世无争的旁观者,不影响集群的正常写性能,还提升读性能,可以用在异地机房数据同步。
四、要点总结
熟悉 Leader
选举的底层理论,可以很好的应对集群的迁移和扩缩容。ZooKeeper
在Leader选举期间和正常服务个数不过半数都无法对外提供服务,并且会丢弃一些未完成的事务,以保证数据一致,所以它是CP
,即保证数据一致性(Consistency
)和分区容错性(Partition Tolerance
),但不保证可用性(Available
)。
本篇要点总结如下:
Leader
选举,先比较ZXID
,ZXID
较大的获得更多选票,ZXID
相等,比较myid
,myid
较大的获得更多选票。- 票数过半即可选出
Leader
,后来者则自动成为Follower
。 - 故障恢复,
Leader
重选,会丢弃未完成的事务。 Observer
虽然没有投票权,也不决定过半机制,但是同样可以和Leader
建立连接,同步数据。这一特点可以用于异地机房同步数据和扩容上,极大提升读性能但对写性能影响极小。
五、参考资料
- 书籍:《从Paxos到Zookeeper分布式一致性原理与实践》
- https://www.bilibili.com/video/BV1to4y1C7gw
- Migrating Kafka’s Zookeeper With No Downtime
如若文章有错误理解,欢迎批评指正,同时非常期待你的评论、点赞和收藏。
如果想了解更多优质文章,和我更密切的学习交流,请关注如下同名公众号【徐同学呀】,期待你的加入。
注:《ZooKeeper-分布式过程协同技术详解》和 《从Paxos到Zookeeper分布式一致性原理与实践》pdf版本由于版权问题无法在CSDN上传,有需要这两本PDF的请关注公众号:徐同学呀,回复zkpdf获取。
文章来源: blog.csdn.net,作者:徐同学呀,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_36586120/article/details/120473058
- 点赞
- 收藏
- 关注作者
评论(0)