提到zookeeper选举算法,就不得不提Paxos算法,由于zookeeper选举算法是Paxos算法的一个变种;算法
Paxos要解决的问题是:在一个分布式网络环境中有众多的参与者,可是每一个参与者都不可靠,可能随时掉线等,这时这些参与者如何针对某个见解达成一致;apache
相似的问题现实生活中有不少,好比一个团队要组织团建,团队中有10我的,每一个人都有本身想去的地方,如何就团建的目的地达成一致?服务器
最简单的方式是把团队全体叫到会议室开会,很快就能够根据少数服从多数的原则,肯定一个大多数人都满意的目的地;网络
若是将问题改成:团队10我的分别在世界的10个地方出差,做息时间各不相同,而且只能经过邮件联系,这时如何肯定团建的目的地?并发
https://en.wikipedia.org/wiki/Paxos_(computer_science)less
https://zh.wikipedia.org/zh-cn/Paxos%E7%AE%97%E6%B3%95 分布式
Paxos is a family of protocols for solving consensus in a network of unreliable processors. Consensus is the process of agreeing on one result among a group of participants. This problem becomes difficult when the participants or their communication medium may experience failures.ide
Paxos describes the actions of the processors by their roles in the protocol: client, acceptor, proposer, learner, and leader. In typical implementations, a single processor may play one or more roles at the same time. This does not affect the correctness of the protocol—it is usual to coalesce roles to improve the latency and/or number of messages in the protocol.学习
client有不少个,而且每一个client都有不少idea,可是只有一个client的一个idea最终会被你们接受;client想让一个idea被接收,首先会把idea告诉proposor,proposor收到一个idea以后会提交给多个acceptor进行表决,若是超过半数的acceptor表决经过,则表示idea被你们接受;learner会及时收到acceptor的表决结果;flex
因为实际表决过程是并发的,因此表决过程分为多个阶段,而且增长版本version的概念,这里有点相似于乐观锁;
一个形象的例子是在某个腐败的国家里,政府有一个项目要招标,而后有不少公司(client)都想拿到该项目(idea),决定该项目给谁的是有一个政府内部高层人士(acceptor)小组讨论决定,可是他们深藏不漏,公司须要经过一些政商通吃的中介(proposor),给高层人士输送贿赂(version),每一个高层人士收到一个贿赂以后会表示再也不接受不高于这个贿赂的其余贿赂而且支持当前这个贿赂的公司,若是一个公司可以成功贿赂小组中多数高层人士,那么这个公司能够拿到这个项目;
首先将议员的角色分为 proposers,acceptors,和 learners(容许身兼数职)。proposers 提出提案,提案信息包括提案编号和提议的 value;acceptor 收到提案后能够接受(accept)提案,若提案得到多数 acceptors 的接受,则称该提案被批准(chosen);learners 只能“学习”被批准的提案。划分角色后,就能够更精确的定义问题:
做者经过不断增强上述3个约束(主要是第二个)得到了 Paxos 算法。
P1:一个 acceptor 必须接受(accept)第一次收到的提案。
P1a:当且仅当acceptor没有回应过编号大于n的prepare请求时,acceptor接受(accept)编号为n的提案。
P2:一旦一个具备 value v 的提案被批准(chosen),那么以后批准(chosen)的提案必须具备 value v。
P2a:一旦一个具备 value v 的提案被批准(chosen),那么以后任何 acceptor 再次接受(accept)的提案必须具备 value v。
P2b:一旦一个具备 value v 的提案被批准(chosen),那么之后任何 proposer 提出的提案必须具备 value v。
P2c:若是一个编号为 n 的提案具备 value v,那么存在一个多数派,要么他们中全部人都没有接受(accept)编号小于 n 的任何提案,要么他们已经接受(accept)的全部编号小于 n 的提案中编号最大的那个提案具备 value v。
每一个zookeeper服务器都至关于client+proposor+acceptor+learner
Vote(提案编号、提议的 value):myid、zxid、epoch
初始值:
currentVote = new Vote(myid, getLastLoggedZxid(), getCurrentEpoch());
其余人的Vote:
HashMap<Long, Vote> recvset = new HashMap<Long, Vote>();
zookeeper的选举算法作了不少简化,将Paxos的value和version合并成Vote,是为了保证可以在最短的时间内选举出新的leader,同时避免数据丢失和数据同步,来看如下几种状况:
选举核心类及调用流程:
org.apache.zookeeper.server.quorum.Election
org.apache.zookeeper.server.quorum.FastLeaderElection implements Election
lookForLeader
sendNotifications
totalOrderPredicate
termPredicate
org.apache.zookeeper.server.quorum.flexible.QuorumMaj
containsQuorum
QuorumPeer.setPeerState
是否超过半数判断
public boolean containsQuorum(HashSet<Long> set){ return (set.size() > half); }
Vote大小判断
protected boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch) { LOG.debug("id: " + newId + ", proposed id: " + curId + ", zxid: 0x" + Long.toHexString(newZxid) + ", proposed zxid: 0x" + Long.toHexString(curZxid)); if(self.getQuorumVerifier().getWeight(newId) == 0){ return false; } /* * We return true if one of the following three cases hold: * 1- New epoch is higher * 2- New epoch is the same as current epoch, but new zxid is higher * 3- New epoch is the same as current epoch, new zxid is the same * as current zxid, but server id is higher. */ return ((newEpoch > curEpoch) || ((newEpoch == curEpoch) && ((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId))))); }