谁来当家做主,国不可一日无君,谁来协调?也不可诸雄四起,听谁的?
当zookeeper集群启动时,会自动进入选举,选出一个leader出来。
1、刚启动的时候,zookeeper集群中的每一个节点都会推荐自己成为leader,并且将自己的选举信息发送给其他节点,进行两两比较。
2、通过多轮比较,最后胜出的那个节点就是leader节点。
3、节点发送给其他节点的选举信息都包括哪些内容?
当前节点的最大事务id(事务id越大,说明当前节点处理的事务越多,做的工作越多,理应成为leader节点)
选举编号——也就是服务器id,也就是我们给定的myid
逻辑时钟值:用来控制选举的轮数。同一轮投票中逻辑时钟值时相同的。
比较原则
比较两个节点的最大事务id,谁大谁赢
如果事务id一致,比较myid,谁大谁赢
如果某个节点胜过了一半的节点,在加上自己推荐自己就已经过半选举了,可以成为leader
举例
依次启动3个节点的zk集群,当启动第二个节点时,第二个节点会和第一个节点进行比较,两个节点的最大事务id相同,因为刚部署的集群。然后比较myid,第二个节点大。第二个节点胜过第一个节点,并且加上自己,已经有2个节点支持第二个节点了,所以第二个节点会成为leader,当启动第三个节点时,应为已经存在leader,所以第三个节点会作为新增节点加入集群。
选举中的其他规则
1、Zookeeper为了稳定性考虑,一旦选出了leader,新添加的节点无论怎么样都只会是follower节点
2、当leader节点宕机或者丢失连接之后,剩余的zk节点会重新选举出来一个leader节点。原leader节点恢复之后,会作为新的节点加入,不会再成为leader节点。
脑裂
由于原来的leader节点丢失连接后,其他节点会重新选举,就有可能会出现脑裂问题(双主问题)
1、脑裂的产生条件:
集群之间由于网络波动等原因,被分裂成了两个集群,含有leader节点的部分集群被分裂出去。剩下的集群由于没有leader节点,将会重新尝试选举出来一个新的leader节点。当网络恢复之后,一个集群中就有了两个leader节点,集群中剩余的节点就不知道听从哪个节点的指令,从而产生数据混乱等问题,就是脑裂了。
2、如何解决脑裂?
脑类出现的条件包括集群产生了分裂,这个无法避免;
第二个条件是,集群中又重新选举出了新的leader,选举机制中的过半原则,保证了如果集群分裂成两个,少于1半节点的集群是无法选举产生新的leader的。
在zk集群中,如果存活的节点个数不足一半,那么剩余的节点既不会选举也不会对外提供服务。
所以zk集群的节点个数往往都是奇数个,奇数个比较容易满足过半原则(选举需要过半,请求响应需要过半)
tips:如果集群中的节点个数少于一半,比如3个节点只启动了一个,查询状态时报错,probably not running
另外一种集群分裂
当含有leader的集群作为少数节点被分裂出去后怎么办?在zk集群中,会对每一次选举出来的leader分配一个 全局递增的编号,叫做epochid;当leader选举出来之后,会将自己的epochid分发给每一个follower,此后follower在接收到命令的时候会比较epochid,丢弃掉小的epochid的leader发过来的命令。zookeeper会自动的将具有小的epochid的节点进行重启,重启之后之前的那个leader节点就变成了了follower节点。
【leader作为少数节点分裂出去以后,多数节点的部分会重新选举出来一个leader节点,当集群恢复之后,集群中出现两个leader节点,通过比较epochid之后,老的leader节点会重启并且成为follower节点】
配置的dataDir目录下的version-2目录下,acceptedEpoch 和 currentEpoch 文件中,记录了当前接受的epochid,如果为3表明当前leader节点是第三次被选成leader的。
延伸阅读
https://blog.csdn.net/long290046464/article/details/81408624