作者:吴香伟 发表于 2014/09/11

版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明

Paxos算法存在活锁问题。从节点中选出Leader,然后将所有对数据的修改都通过Leader作为提案提出,可以让算法快速收敛。Leader的选举规则是,由当前活动的Monitor节点中rank值最小的节点当选。选举不仅会产生Leader还将确定Quorum成员,Quorum成员就是那些支持新Leader节点当选Leader的节点。因此,虽然不能保证Leader的rank值是所有节点中最小的,但是可以保证它的值在Quorum中是最小的。Quorum是Monitor中的多数派,也就是说它的成员数目必须大于N/2+1N为Monitor节点数目。

Leader选举过程大致可以分成以下3个步骤:首先,Proposer提出提案,发送propose消息给所有的Monitor节点。其次,Monitor节点(Acceptor)接收到proposer消息,如果接受提案则回复ack消息。最后,Proposer统计接收到的ack消息,向其它节点发送victory消息宣布赢得Leader选举并同步数据。

提出propose消息

在选举Leader过程中,epoch担当非常重要的角色。它有以下几个方面的作用:

  1. 代表逻辑时间。正常情况下,Quorum中各个节点的epoch值应该是相等的。当节点离线后,它的epoch值被保存在数据库中,重新上线后它的epoch值比其它节点的小。在处理propose消息时,Acceptor节点根据epoch值来判断消息是不是最新的。
  2. 用于判断当前节点是否处于Leader选举状态。当epoch为奇数时,说明节点处于选举状态;选举结束后,epoch值会递增为偶数并同步到所有的Quorum成员。

Proposer提出选举提案前,先从数据库中读取epoch值,并将其递增到奇数。

处理propose消息

Acceptor处理propose消息时,主要考虑epoch(代表时间)和rank两个因素:首先,判断propose消息是否是由于网络延迟导致的旧提案,若是则拒绝提案;其次,判断proposer的rank值是否是它知道的rank中最小的,若是则接受并且承诺不接受rank值比提案的rank值更大的提案。

处理ack消息

Ack消息对应Paxos的Accept消息。

Ack消息有两个作用:一种情况是通知Proposer它的提案被发送ack消息的Acceptor接受了;另一种情况是,Acceptor已经接受了提案(因为它的rank值小于Acceptor),但是存在提案号更高的提案,Proposer应该放弃当前的提案,使用更高的提案号重新提出提案。

例子

假设原来已经存在两个节点A和B,现在加入新节点C,并且节点C的rank值是三者中最小的。节点C加入时,将引发选举:

  1. 节点C向其余两个节点发送propose消息,将自己设置为Leader。由于节点C是新加入的,所以它的epoch值从0开始递增;
  2. 节点A、B接受到消息后,发现节点C的epoch值比较旧。但由于节点C不在Quorum中,说明这个提案不是由于网络延迟导致的旧提案。并且节点C的rank值比自己小,所以接受提案并提醒对方更新epoch值
  3. 节点C接收到节点A和B的ack消息,发现自己的epoch值比它们都小,所以用它们的epoch更新自己,并重新发送propose消息,提出提案。
  4. 节点A、B接受到新propose消息,发现节点C的epoch值比自己的新,于是更新自己的epoch值(持久化到磁盘)。另外,节点C的rank值也比自己的小,所以接受提案。
  5. 节点C接收到节点A和B对新提案的Ack消息,赢得选举。
  6. 节点C向其余节点发送victory消息,更新Quorum以及Leaders角色。

如果新加入节点的rank值的不是最小的,那么当它的proposer消息发送到rank值比自己更小的节点时,会引发节点提出提案参加候选。这种情况下,新节点虽然不会赢得选举,但是能够让自己加入到Quorum多数派。

疑问:多Leader情况

假设有A到E共5个节点,它们的rank值是依次递增的。另外,A和B之间相互不通。当5个节点的epoch都相同,节点A和B同时提出提案(此时提案的epoch也相同)。

-----------------------
A B C D E
A + - + + +
B - + + + +
-----------------------

如果B的propose先达到C、D和E节点,那么这三个节点都会接受B节点的提案。这样,节点B就获得了多数派的支持,选举超时后它将赢得选举。当节点A的propose消息到达C、D和E节点时,由于A节点的rank值要比它们已经接受的B节点的rank值小,所以这三个节点将接受A节点的提案。

这样,节点A和节点B都认为赢得了选举,都将自己初始化为Leader,都可以接受来自客户端对Cluster map的修改。

这种情况下,如果节点A的propose消息早于B节点的消息到达C、D、E中两个或两个以上的节点时,B节点将不能赢得选举。因为Acceptor承诺不接受rank值更大的提案,B节点后达到时将被拒绝。

其它

变量说明

start_stamp: 提出提案的时间戳
acked_me: 回复ack消息的节点集合
electing_me: “选我”,标记自己为候选人
leader_acked: 接受的提案的内容,没接受提案时该值默认为-1;

接口说明

1、选举的入口函数为Monitor::start_election(),进入该函数时将Monitor的状态更改为STATE_ELECTING。Elector::start()为private方法,必须经过Elector::call_election()方法调用;
2、选举成功后进入Monitor::win_election()函数将Monitor状态修改为STATE_LEADER,选举失败的节点进入Monitor::lose_election()函数将Monitor的状态修改为STATE_PEON;

参考资料

1、ceph work flow

2、MONITOR CONFIG REFERENCE

Ceph剖析:Leader选举的更多相关文章

  1. Ceph剖析:Paxos算法实现

    作者:吴香伟 发表于 2014/10/8 版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明 Recovery阶段 在Leader选举成功后,Leader和Peon都 ...

  2. 【分布式】Zookeeper的Leader选举

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  3. Curator leader 选举(一)

    要想使用Leader选举功能,需要添加recipes包,可以在maven中添加如下依赖: <dependency> <groupId>org.apache.curator< ...

  4. Zookeeper-Zookeeper leader选举

    在上一篇文章中我们大致浏览了zookeeper的启动过程,并且提到在Zookeeper的启动过程中leader选举是非常重要而且最复杂的一个环节.那么什么是leader选举呢?zookeeper为什么 ...

  5. ZOOKEEPER3.3.3源码分析(四)对LEADER选举过程分析的纠正

    很抱歉,之前分析的zookeeper leader选举算法有误,特此更正说明. 那里面最大的错误在于,leader选举其实不是在大多数节点通过就能选举上的,这一点与传统的paxos算法不同,因为如果这 ...

  6. 第四章 Leader选举算法分析

    Leader选举 学习leader选举算法,主要是从选举概述,算法分析与源码分析(后续章节写)三个方面进行. Leader选举概述 服务器启动时期的Leader选举 选举的隐式条件便是ZooKeepe ...

  7. zookeeper系列之五—Leader选举算法

    leader选举算法 zookeeper server内部原理 zookeeper client

  8. zookeeper进行leader选举

    一.如何进行leader选举 创建 /lj/producer和/lj/master/producer外层节点 创建临时顺序节点 判断自己是否是master节点(判断流程:遍历/lj/producer节 ...

  9. 【Zookeeper】源码分析之Leader选举(二)

    一.前言 前面学习了Leader选举的总体框架,接着来学习Zookeeper中默认的选举策略,FastLeaderElection. 二.FastLeaderElection源码分析 2.1 类的继承 ...

随机推荐

  1. Tesla P4 在深度学习上的性价比辗压目前所有量产的FPGA

    7000的价格, 5.5T FP, 75W不到的功耗,性能接近M40,敢问目前有哪个量产的FPGA能做到?还不算开发和维护的难度...KU115光PCIE+DMA+DDR4 controller+AX ...

  2. js部分总结

    1 currentStyle 可以获取行间样式,但是不兼容 其他浏览器用getComputedStyle(div,null)这个ie低级版本不兼容; if(div.currentStyle){ } e ...

  3. javascript date picker

    一个简洁的date picker <html><head><meta http-equiv="Content-Type" content=" ...

  4. iOS原型模式

    原型模式:大部分重复,只有一小部分不同的情况下,为了代码清晰和避免麻烦,用原型模式,会更方便一点 // 学生1 StudentModel *stu1 = [[StudentModel alloc] i ...

  5. DUBBO参数验证

    public class ValidationParameter implements Serializable {           private static final long seria ...

  6. linux 获取线程号

    #include <sys/types.h> pid_t gettid(void); 如果系统库里没有,则可以这样做: #include <sys/syscall.h> pid ...

  7. ---bind 配置

    http://blog.csdn.net/zjunjun/article/details/7419125

  8. HTML DOM 对象简单介绍

    文档对象模型(Document Object Model,DOM)是DHTML的基础. 常用对象:1)window对象:表示对象浏览器窗口(选项卡)对象.2)document对象:代表整个网页,是客户 ...

  9. hg常用命令

    关于hg命令选项 如果你是在windows系统下,使用的是图像界面,你很可能不常用它.但是一旦你了解这些命令之后,会觉得很方便.hg有很多命令,这些命令都有一定的选项,在开始的时候,只知道用它,有时候 ...

  10. 邮箱验证 各种邮箱的smtp

    常见邮箱的SMTP设置 QQ 邮箱举例:(地址test@qq.com)(账号test)(密码***)(SMTP服务smtp.qq.com)(端口25)(注意:请手动开通SMTP功能,通过网页登录qq邮 ...