Zookeeper选举过程描述与状态迁移
F1.FastLeaderElection类初始过程
?
?
F2.QuorumCnxManager内部结构
?
F3.FastLeaderElection选举过程
?
?F4.选举过程
a) 如果proposalEpoch > peerEpoch,校验成功.此时的peerEpoch是整个集群server最近一次投票成功时的epoch;每次投票成功,每个server就会把epoch写入到文件.否则,参见b) b) 如果proposalEpoch = peerEpoch,并且proposalZxid > currentZxid,校验成功.currentZxid为当前server的zkDatabase中持有的最大的zxid.否则,参见c) c) 如果proposalZxid = currentZxid,并且”提议者”的sid比当前server的sid大,校验成功.否则失败.最终将由sid来决定,是否接受此次”提议”. Server本地保持者一份当前投票的最新(高)的提议副本,此副本包括epoch/zxid/leader(sid);如果server从消息中发现有更好的提议,将会替换本地的这些信息.并在适当的时机,将自己收集到的提议副本发送给其他”提议者”.知道最终达成一致.?如果”提议”被当前server校验通过,将被封装成一个更加简小的对象Vote(投票).”投票”将会被放入一个Map中,key为sid,value就是”投票”,确保每个server都参与而且只有一个有效的vote.“断言是否成功”:截止到目前,当前”提议”是否已经是”多数派”,如果是,即可结束投票,leader已经在集群中产生.(可以提前确定leader). Outofelection是个map,key为sid,value为vote(投票);它的本意是存储那些在非投票期间所产生的”vote”(类似于票据),在失效的server重新加入集群,将会触发”选举”,此时其他server的”提议”将会被加入到outofelection,当前server根据此map来判断是否存在”多数派”,如果集群处于”危险期”(少数派),那么新加入的server选举直到”多数派”出现.新server加入,投票时还会进行CheckLeader操作.
if (termPredicate(outofelection, new Vote(n.leader,n.zxid, n.electionEpoch, n.peerEpoch, n.state)) && checkLeader(outofelection, n.leader, n.electionEpoch)) {synchronized(this){logicalclock = n.electionEpoch;self.setPeerState((n.leader == self.getId()) ?ServerState.LEADING: learningState());}Vote endVote = new Vote(n.leader, n.zxid, n.peerEpoch);leaveInstance(endVote);return endVote;}?
[引导:Leader选举补充部分]
?
Leader: ?Cluster环境中操作"调度者",负责"数据一致性"的控制,主要包括"write操作"/Session过期控制等.
Follower: "跟随者",它是和Leader共同构成Cluster多数派,直接负责接收Client的read和write操作,并转发write操作给"Leader".
Observer(“围观者”):
在ZK server中,有一种特殊的server类型,是Observer(read-only),它可以在不影响写入性能的同时扩展zk。zk之所以设计这种类型的server,是可以理解的;如果一个cluster中不断新增的voting member(follower),将会导致write性能下降,这归因于write操作需要至少半数的follower同意才能被执行,所以这种“提议/投票”的开支会随着“follower”的增加而增加。
我们引入了一个新的server类型,就是Observer;它对于解决这种问题很有帮助,而且跟一步提高了ZK的扩展性。Observer为non-voting成员,即不参与leader选举和其他操作的“提议”,它就像一个“围观者”一样只会接受投票的结果,而不是投票的协议。除了这个简单的区别之外,它和follower几乎一样。client也可以和它们建立链接,发送read和write请求。Observer和Follower一样把write请求转发给leader,只是它们然后就是简单的等待(hear)此操作的投票结果;因此我们能够在无损性能的情况下增加数个observer。
Observer还有其他的优点,因为它们不参与投票,他们不是ZK成员的核心部分;所以即使它们失效了,或者离群了,也不会对ZK 服务带来任何不利影响。Observer可以链接比followers更加不可靠的网路。
Observer类中可以看到它对各种消息的处理,Observer不是ZAB的一部分,也参与提议,在processPacket()方法中可见,observer会忽略PROPOSAL/COMMIT类型的请求,而增加了一个INFORM,这个请求类型是为Observer设计的,当proposal成功执行后,会把数据packet以INFORM消息类型发给Observer(Follower不关系此类型),那么observer即可以在本地应用最新的数据。
?
设置Observer非常简单,只需要将zoo.cfg中peerType=observer即可。
简单的使用场景:
作为数据中心桥:如果构成ZK环境有2个数据中心,那么2个数据中心的网络延迟是一个很棘手的问题,(延迟)可能会导致“假故障”问题(超时等)。不过可以将其中一个datacenter全部设置为observer,这样可以避免这些问题,而且链接observer的客户端仍然可以看到问题提议(issue proposal)。(zk cluster中一部分机器作为observer,这部分及其可能位于位置较远的其他地区,为了不让这种“位置”距离影响了zk服务,只能这这部分zk server成为observer,比如你的zk服务一部分在中国,另部分可能位于美国机房)。
?
?
?