Zookeeper快速领导者选举原理

作者: 1点25 | 来源:发表于2019-06-17 16:28 被阅读1次

    本文略长,更适合在电脑端观看,可以收藏或直接关注微信公众号:1点25

    人类选举的基本原理

    正常情况下,选举是一定要投票的。

    我们应该都经历过投票,在投票时我们可能会将票投给和我们关系比较好的人,如果你和几个候选人都比较熟,这种情况下你会将选票投给你认为能力比较强的人,如果你和几个候选人都不熟,并且你自己也是候选人的话,这时你应该会认为你是这些候选人里面最厉害的那个人,大家都应该选你,这时你就会去和别人交流以获得别人的投票,但是很有可能在交流的过程中,你发现了比你更厉害的人,这时你如果脸皮不是那么厚的话,你应该会改变你的决定,去投你觉得更厉害的人,最终你将得到在你心中认为最厉害的人,且将票投给他,选票将会放在投票中,最后从投票箱中进行统计,获得票数最多的人当选。

    在这样一个选举过程中我们提炼出四个基本概念:

    1. 个人能力:投我认为能力最强的人,这是投票的基本规则
    2. 改票:能力最强的人是逐渐和其他人沟通之后的结果,类似改票,先投给A,但是后来发现B更厉害,则改为投B
    3. 投票箱:所有人公用一个投票箱
    4. 领导者:获得投票数最多的人为领导者

    Zookeeper选举的基本原理

    Zookeeper集群模式下才需要选举。

    Zookeeper的选举和人类的选举逻辑类似,Zookeeper需要实现上面人类选举的四个基本概念;

    1. 个人能力:Zookeeper是一个数据库,集群中节点的数据越新就代表此节点能力越强,而在Zookeeper中可以通事务id(zxid)来表示数据的新旧,一个节点最新的zxid越大则该节点的数据越新。所以Zookeeper选举时会根据zxid的大小来作为投票的基本规则。
    2. 改票:Zookeeper集群中的某一个节点在开始进行选举时,首先认为自己的数据是最新的,会先投自己一票,并且把这张选票发送给其他服务器,这张选票里包含了两个重要信息:zxidsid,sid表示这张选票投的服务器id,zxid表示这张选票投的服务器上最大的事务id,同时也会接收到其他服务器的选票,接收到其他服务器的选票后,可以根据选票信息中的zxid来与自己当前所投的服务器上的最大zxid来进行比较,如果其他服务器的选票中的zxid较大,则表示自己当前所投的机器数据没有接收到的选票所投的服务器上的数据新,所以本节点需要改票,改成投给和刚刚接收到的选票一样。
    3. 投票箱:Zookeeper集群中会有很多节点,和人类选举不一样,Zookeeper集群并不会单独去维护一个投票箱应用,而是在每个节点内存里利用一个数组来作为投票箱。每个节点里都有一个投票箱,节点会将自己的选票以及从其他服务器接收到的选票放在这个投票箱中。因为集群节点是相互交互的,并且选票的PK规则是一致的,所以每个节点里的这个投票箱所存储的选票都会是一样的,这样也可以达到公用一个投票箱的目的。
    4. 领导者:Zookeeper集群中的每个节点,开始进行领导选举后,会不断的接收其他节点的选票,然后进行选票PK,将自己的选票修改为投给数据最新的节点,这样就保证了,每个节点自己的选票代表的都是自己暂时所认为的数据最新的节点,再因为其他服务器的选票都会存储在投票箱内,所以可以根据投票箱里去统计是否有超过一半的选票和自己选择的是同一个节点,都认为这个节点的数据最新,一旦整个集群里超过一半的节点都认为某一个节点上的数据最新,则该节点就是领导者。

    通过对四个概念的在Zookeeper中的解析,也同时介绍了一下Zookeeper领导者选举的基本原理,只是说选举过程中还有更多的细节需要我们了解,下面我结合源码来给大家详细的分析一下Zookeeper的快速领导者选举原理。

    领导者选举入口

    ZooKeeperServer表示单机模式中的一个zkServer。
    QuoruPeer表示集群模式中的一个zkServer。
    QuoruPeer类定义如下:

    public class QuorumPeer extends ZooKeeperThread implements QuorumStats.Provider
    

    定义表明QuorumPeer是一个ZooKeeperThread,表示是一个线程。
    当集群中的某一个台zkServer启动时QuorumPeer类的start方法将被调用。

    public synchronized void start() {
            loadDataBase(); // 1
            cnxnFactory.start(); // 2
            startLeaderElection(); // 3 
            super.start();  // 4
        }
    
    1. zkServer中有一个内存数据库对象ZKDatabase, zkServer在启动时需要将已被持久化的数据加载进内存中,也就是加载至ZKDatabase。
    2. 这一步会开启一个线程来接收客户端请求,但是需要注意,这一步执行完后虽然成功开启了一个线程,并且也可以接收客户端线程,但是因为现在zkServer还没有经过初始化,实际上把请求拒绝掉,知道zkServer初始化完成才能正常的接收请求。
    3. 这个方法名很有误导性,这个方法并没有真正的开始领导选举,而是进行一些初始化
    4. 继续启动,包括进行领导者选举、zkServer初始化。

    领导者选举策略

    上文QuorumPeer类的startLeaderElection会进行领导者选举初始化。
    首先,领导者选举在Zookeeper中有3种实现:

    image.png

    相关文章

      网友评论

        本文标题:Zookeeper快速领导者选举原理

        本文链接:https://www.haomeiwen.com/subject/bvxzfctx.html