zookeeper选举状态介绍 摘自https://cloud.tencent.com/developer/news/303891
zookeeper集群
配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。

这篇主要分析leader的选择机制,zookeeper提供了三种方式:
LeaderElection
AuthFastLeaderElection
FastLeaderElection
默认的算法是FastLeaderElection,所以这篇主要分析它的选举机制。
选择机制中的概念
服务器ID
比如有三台服务器,编号分别是1,2,3。
编号越大在选择算法中的权重越大。
数据ID
服务器中存放的最大数据ID.
值越大说明数据越新,在选举算法中数据越新权重越大。
逻辑时钟
或者叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。
选举状态
LOOKING,竞选状态。
FOLLOWING,随从状态,同步leader状态,参与投票。
OBSERVING,观察状态,同步leader状态,不参与投票。
LEADING,领导者状态。
选举消息内容
在投票完成后,需要将投票信息发送给集群中的所有服务器,它包含如下内容。
服务器ID
数据ID
逻辑时钟
选举状态
选举流程图
因为每个服务器都是独立的,在启动时均从初始状态开始参与选举,下面是简易流程图。

选举状态图
描述Leader选择过程中的状态变化,这是假设全部实例中均没有数据,假设服务器启动顺序分别为:A,B,C。

源码分析
QuorumPeer
主要看这个类,只有LOOKING状态才会去执行选举算法。每个服务器在启动时都会选择自己做为领导,然后将投票信息发送出去,循环一直到选举出领导为止。
publicvoidrun() {
//.......
try{
while(running) {
switch(getPeerState()) {
caseLOOKING:
if(Boolean.getBoolean("readonlymode.enabled")) {
//...
try{
//投票给自己...
setCurrentVote(makeLEStrategy().lookForLeader());
}catch(Exception e) {
//...
}finally{
//...
}
}else{
try{
//...
setCurrentVote(makeLEStrategy().lookForLeader());
}catch(Exception e) {
//...
}
}
break;
caseOBSERVING:
//...
break;
caseFOLLOWING:
//...
break;
caseLEADING:
//...
break;
}
}
}finally{
//...
}
}
FastLeaderElection
它是zookeeper默认提供的选举算法,核心方法如下:具体的可以与本文上面的流程图对照。
publicVote lookForLeader()throwsInterruptedException {
//...
try{
HashMaprecvset =newHashMap();
HashMapoutofelection =newHashMap();
intnotTimeout = finalizeWait;
synchronized(this){
//给自己投票
logicalclock.incrementAndGet();
updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());
}
//将投票信息发送给集群中的每个服务器
sendNotifications();
//循环,如果是竞选状态一直到选举出结果
while((self.getPeerState() == ServerState.LOOKING) &&
(!stop)){
Notification n = recvqueue.poll(notTimeout,
TimeUnit.MILLISECONDS);
//没有收到投票信息
if(n ==null){
if(manager.haveDelivered()){
sendNotifications();
}else{
manager.connectAll();
}
//...
}
//收到投票信息
elseif(self.getCurrentAndNextConfigVoters().contains(n.sid)) {
switch(n.state) {
caseLOOKING:
// 判断投票是否过时,如果过时就清除之前已经接收到的信息
if(n.electionEpoch > logicalclock.get()) {
logicalclock.set(n.electionEpoch);
recvset.clear();
//更新投票信息
if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,
getInitId(), getInitLastLoggedZxid(), getPeerEpoch())) {
updateProposal(n.leader, n.zxid, n.peerEpoch);
}else{
updateProposal(getInitId(),
getInitLastLoggedZxid(),
getPeerEpoch());
}
//发送投票信息
sendNotifications();
}elseif(n.electionEpoch
//忽略
break;
}elseif(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,
proposedLeader, proposedZxid, proposedEpoch)) {
//更新投票信息
updateProposal(n.leader, n.zxid, n.peerEpoch);
sendNotifications();
}
recvset.put(n.sid,newVote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));
//判断是否投票结束
if(termPredicate(recvset,
newVote(proposedLeader, proposedZxid,
logicalclock.get(), proposedEpoch))) {
// Verify if there is any change in the proposed leader
while((n = recvqueue.poll(finalizeWait,
TimeUnit.MILLISECONDS)) !=null){
if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,
proposedLeader, proposedZxid, proposedEpoch)){
recvqueue.put(n);
break;
}
}
if(n ==null) {
self.setPeerState((proposedLeader == self.getId()) ?
ServerState.LEADING: learningState());
Vote endVote =newVote(proposedLeader,
proposedZxid, proposedEpoch);
leaveInstance(endVote);
returnendVote;
}
}
break;
caseOBSERVING:
//忽略
break;
caseFOLLOWING:
caseLEADING:
//如果是同一轮投票
if(n.electionEpoch == logicalclock.get()){
recvset.put(n.sid,newVote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));
//判断是否投票结束
if(termPredicate(recvset,newVote(n.leader,
n.zxid, n.electionEpoch, n.peerEpoch, n.state))
&& checkLeader(outofelection, n.leader, n.electionEpoch)) {
self.setPeerState((n.leader == self.getId()) ?
ServerState.LEADING: learningState());
Vote endVote =newVote(n.leader, n.zxid, n.peerEpoch);
leaveInstance(endVote);
returnendVote;
}
}
//记录投票已经完成
outofelection.put(n.sid,newVote(n.leader,
IGNOREVALUE, IGNOREVALUE, n.peerEpoch, n.state));
if(termPredicate(outofelection,newVote(n.leader,
IGNOREVALUE, IGNOREVALUE, n.peerEpoch, n.state))
&& checkLeader(outofelection, n.leader, IGNOREVALUE)) {
synchronized(this){
logicalclock.set(n.electionEpoch);
self.setPeerState((n.leader == self.getId()) ?
ServerState.LEADING: learningState());
}
Vote endVote =newVote(n.leader, n.zxid, n.peerEpoch);
leaveInstance(endVote);
returnendVote;
}
break;
default:
//忽略
break;
}
}else{
LOG.warn("Ignoring notification from non-cluster member " + n.sid);
}
}
returnnull;
}finally{
//...
}
}
判断是否已经胜出
默认是采用投票数大于半数则胜出的逻辑。
选举流程简述
目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking。
服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
服务器5启动,后面的逻辑同服务器4成为小弟。
zookeeper选举状态介绍 摘自https://cloud.tencent.com/developer/news/303891的更多相关文章
- 有状态(Stateful)应用的容器化 - 云+社区 - 腾讯云 https://cloud.tencent.com/developer/article/1020178
有状态(Stateful)应用的容器化 - 云+社区 - 腾讯云 https://cloud.tencent.com/developer/article/1020178
- 我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=i5j7gwrxj9x5
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=i5j7gwrxj9x5
- 我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3cp8ng15g94wc
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3cp8ng15g94wc
- flask 框架 转载:https://cloud.tencent.com/developer/article/1465949
1.cookie.py """ - 解释: 用来保持服务器和浏览器交互的状态的, 由服务器设置,存储在浏览器 - 作用: 用来做广告推送 - cookie的设置和获取 - ...
- flask 框架 转载:https://cloud.tencent.com/developer/article/1465968
特点总结: 类名称---->数据库表名 类属性---->数据库字段 类的对象----->数据库表中的一行一行数据 3.ORM操作注意(理解) 1/因为SQLALChemy去app身上 ...
- 【转】Zookeeper学习---zookeeper 选举机制介绍
[原文]https://www.toutiao.com/i6593162565872779784/ zookeeper集群 配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的 ...
- go-micro介绍 摘自https://www.cnblogs.com/s0-0s/p/6874800.html
Micro 架构与设计 翻译自 Micro architecture & design patterns for microservices 注: 原文作者即 Micro 框架的开发者. 过去 ...
- 【分布式】Zookeeper的Leader选举-选举过程介绍(经典的Paxos算法解析)
一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...
- zookeeper 选举机制 和 eruake
zookeeper简介: 在分布式环境中,多个服务之间协调一致.有提供分布式锁.服务配置.实现分布式领域CAP(consistency一致性,Availiablity高可用,patition tolr ...
随机推荐
- Jquery的deferred对象,看这2篇牛人的文章,基本就够了。
http://blog.csdn.net/ligang2585116/article/details/51589073 http://www.ruanyifeng.com/blog/2011/08/a ...
- Django之模板层-自定义过滤器以及标签
自定义标签与过滤器 在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag. 在app中创建templatetags模块(模块名只能是t ...
- 【c++基础】字符数组和string相互转换
字符数组转化成string类型char ch [] = "ABCDEFG";string str(ch);//也可string str = ch;或者char ch [] = &q ...
- nginx的安装 、Nginx默认虚拟主机、nginx用户认证、nginx 域名重定向
1.nginx:官网:www.nginx.org 下载:wget -c http://nginx.org/download/nginx-1.14.0.tar.gz解压:tar -zxvf nginx ...
- awk 相关的复习
1. awk 引用外部变量: aa=666 echo "." | awk -v GET_A=$aa '{print GET_A}' . sort -n fuxi.awk |awk ...
- rest-framework之版本控制
rest-framework之版本控制 本文目录 一 作用 二 内置的版本控制类 三 局部使用 四 全局使用 五 示例 源码分析 回到目录 一 作用 用于版本的控制 回到目录 二 内置的版本控制类 f ...
- (2)Django入门
web框架:把一个请求拆成几部分,每部分做相同的事 python中常用的框架 1.Django:大而全的框架 2.flask:微框架又叫轻量级的框架 3.Tornado:高性能框架 pycharm创建 ...
- 简单的Windows应用程序命名规则
读书:<高质量C++编程指南> 作者对“匈牙利”命名规则做了合理的简化,下述的命名规则简单易用,比较适合于Windows应用软件的开发. l [规则3-2-1]类名和函数名用大写字母开头的 ...
- 【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.5RHS语法
转载至:https://blog.csdn.net/wo541075754/article/details/76651073 RHS语法 使用说明 RHS是满足LHS条件之后进行后续处理部分的统称,该 ...
- Java解析property文件(和静哥说的,SQL执行限定时间写在xml中,增加扩展,在不改源代码基础上)
在Java项目中一些配置参数保存在Property文件中,这样能保证不修改原代码直接修改Property文件. 简单的很,就是在java文件中读取外界的properyt配置文件 PropertyPar ...