Zookeeper选举算法原理

Leader选举

Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。

 (1) 服务器初始化启动。(集群的每个节点都没有数据 → 以SID的大小为准)

 (2) 服务器运行期间无法和Leader保持连接。(集群的每个节点都有数据 ,或者Leader 宕机→ 以ZXID 和 SID 的最大值为准)

1. 服务器启动时期的Leader选举

  若进行Leader选举,则至少需要2台机器,两台的高可用性会差一些,如果Leader 宕机,就剩下一台,自己没办法选举。这里选取3台机器组成的服务器集群为例。

  在集群初始化阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是进入Leader选举过程。选举过程如下

(1) 每个Server发出一个投票。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。

(2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。

(3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下:

· 优先检查ZXID。ZXID比较大的服务器优先作为Leader。(这个很重要:是数据最新原则,保证数据的完整性)

· 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。(集群的节点标识)

  对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0。再比较myid,此时Server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于Server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。

(4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。

(5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。

2. 服务器运行时期的Leader选举

  在Zookeeper运行期间,Leader与非Leader服务器各司其职,即便当有非Leader服务器宕机或新加入,此时也不会影响Leader,但是一旦Leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致。

假设正在运行的有Server1、Server2、Server3三台服务器,当前Leader是Server2,若某一时刻Leader挂了,此时便开始Leader选举。

  选举过程如下:

(1) 变更状态。Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。

(2) 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的ZXID为123,Server3的ZXID为122;在第一轮投票中,Server1和Server3都会投自己,产生投票(1, 123),(3, 122),然后各自将投票发送给集群中所有机器。

(3) 接收来自各个服务器的投票。与启动时过程相同。

(4) 处理投票。与启动时过程相同,此时,Server1将会成为Leader。

(5) 统计投票。与启动时过程相同。

(6) 改变服务器的状态。与启动时过程相同。

2.2 Leader选举算法分析

在3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection选举算法。当一台机器进入Leader选举时,当前集群可能会处于以下两种状态

    · 集群中已经存在Leader。

    · 集群中不存在Leader。

  对于集群中已经存在Leader而言,此种情况一般都是某台机器启动得较晚,在其启动之前,集群已经在正常工作,对这种情况,该机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器而言,仅仅需要和Leader机器建立起连接,并进行状态同步即可。而在集群中不存在Leader情况下则会相对复杂,其步骤如下

(1) 第一次投票。无论哪种导致进行Leader选举,集群的所有机器都处于试图选举出一个Leader的状态,即LOOKING状态,LOOKING机器会向所有其他机器发送消息,该消息称为投票。投票中包含了SID(服务器的唯一标识)和ZXID(事务ID),(SID, ZXID)形式来标识一次投票信息。假定Zookeeper由5台机器组成,SID分别为1、2、3、4、5,ZXID分别为9、9、9、8、8,并且此时SID为2的机器是Leader机器,某一时刻,1、2所在机器出现故障,因此集群开始进行Leader选举。在第一次投票时,每台机器都会将自己作为投票对象,于是SID为3、4、5的机器投票情况分别为(3, 9),(4, 8), (5, 8)。

(2) 变更投票。每台机器发出投票后,也会收到其他机器的投票,每台机器会根据一定规则来处理收到的其他机器的投票,并以此来决定是否需要变更自己的投票,这个规则也是整个Leader选举算法的核心所在,其中术语描述如下

· vote_sid:接收到的投票中所推举Leader服务器的SID。

· vote_zxid:接收到的投票中所推举Leader服务器的ZXID。

· self_sid:当前服务器自己的SID。

· self_zxid:当前服务器自己的ZXID。

  每次对收到的投票的处理,都是对(vote_sid, vote_zxid)和(self_sid, self_zxid)对比的过程。

    规则一:如果vote_zxid大于self_zxid,就认可当前收到的投票,并再次将该投票发送出去。

    规则二:如果vote_zxid小于self_zxid,那么坚持自己的投票,不做任何变更。

    规则三:如果vote_zxid等于self_zxid,那么就对比两者的SID,如果vote_sid大于self_sid,那么就认可当前收到的投票,并再次将该投票发送出去。

    规则四:如果vote_zxid等于self_zxid,并且vote_sid小于self_sid,那么坚持自己的投票,不做任何变更。

  结合上面规则,给出下面的集群变更过程。

(3) 确定Leader。经过第二轮投票后,集群中的每台机器都会再次接收到其他机器的投票,然后开始统计投票,如果一台机器收到了超过半数的相同投票,那么这个投票对应的SID机器即为Leader。此时Server3将成为Leader。

  由上面规则可知,通常那台服务器上的数据越新(ZXID会越大),其成为Leader的可能性越大,也就越能够保证数据的恢复。如果ZXID相同,则SID越大机会越大。

2.3 Leader选举实现细节

1. 服务器状态

  服务器具有四种状态,分别是LOOKING、FOLLOWING、LEADING、OBSERVING。

LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。

FOLLOWING:跟随者状态。表明当前服务器角色是Follower。

LEADING:领导者状态。表明当前服务器角色是Leader。

OBSERVING:观察者状态。表明当前服务器角色是Observer。

 2. 投票数据结构

  每个投票中包含了两个最基本的信息,所推举服务器的SID和ZXID,投票(Vote)在Zookeeper中包含字段如下

id:被推举的Leader的SID。

zxid:被推举的Leader事务ID。

electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作。

peerEpoch:被推举的Leader的epoch。

state:当前服务器的状态。

 

为什么zookeeper集群是单数?

1、容错

由于在增删改操作中需要半数以上服务器通过,来分析以下情况。

2台服务器,至少2台正常运行才行(2的半数为1,半数以上最少为2),正常运行1台服务器都不允许挂掉

3台服务器,至少2台正常运行才行(3的半数为1.5,半数以上最少为2),正常运行可以允许1台服务器挂掉

4台服务器,至少3台正常运行才行(4的半数为2,半数以上最少为3),正常运行可以允许1台服务器挂掉

5台服务器,至少3台正常运行才行(5的半数为2.5,半数以上最少为3),正常运行可以允许2台服务器挂掉

6台服务器,至少3台正常运行才行(6的半数为3,半数以上最少为4),正常运行可以允许2台服务器挂掉

通过以上可以发现,3台服务器和4台服务器都最多允许1台服务器挂掉,5台服务器和6台服务器都最多允许2台服务器挂掉

但是明显4台服务器成本高于3台服务器成本,6台服务器成本高于5服务器成本。这是由于半数以上投票通过决定的。

2、防脑裂

一个zookeeper集群中,可以有多个follower、observer服务器,但是必需只能有一个leader服务器。

如果leader服务器挂掉了,剩下的服务器集群会通过半数以上投票选出一个新的leader服务器。

集群互不通讯情况:

一个集群3台服务器,全部运行正常,但是其中1台裂开了,和另外2台无法通讯。3台机器里面2台正常运行过半票可以选出一个leader。

一个集群4台服务器,全部运行正常,但是其中2台裂开了,和另外2台无法通讯。4台机器里面2台正常工作没有过半票以上达到3,无法选出leader正常运行。

一个集群5台服务器,全部运行正常,但是其中2台裂开了,和另外3台无法通讯。5台机器里面3台正常运行过半票可以选出一个leader。

一个集群6台服务器,全部运行正常,但是其中3台裂开了,和另外3台无法通讯。6台机器里面3台正常工作没有过半票以上达到4,无法选出leader正常运行。

通可以上分析可以看出,为什么zookeeper集群数量总是单出现,主要原因还是在于第2点,防脑裂,对于第1点,无非是正常控制,但是不影响集群正常运行。但是出现第2种裂的情况,zookeeper集群就无法正常运行了。

 

ZooKeeper的脑裂的出现和解决方案

 
出现:

在搭建hadoop的HA集群环境后,由于两个namenode的状态不一,当active的namenode由于网络等原因出现假死状态,standby接收不到active的心跳,因此判断active的namenode宕机,但实际上active并没有死亡。此时standby的namenode就会切换成active的状态,保证服务能够正常使用。若原来的namenode复活,此时在整个集群中就出现2个active状态的namenode,该状态成为脑裂。脑裂现象可能导致这2个namenode争抢资源,从节点不知道该连接哪一台namenode,导致节点的数据不统一,这在企业生产中是不可以容忍的。

解决方案:

1、添加心跳线。

原来两个namenode之间只有一条心跳线路,此时若断开,则接收不到心跳报告,判断对方已经死亡。此时若有2条心跳线路,一条断开,另一条仍然能够接收心跳报告,能保证集群服务正常运行。2条心跳线路同时断开的可能性比1条心跳线路断开的小得多。再有,心跳线路之间也可以HA(高可用),这两条心跳线路之间也可以互相检测,若一条断开,则另一条马上起作用。正常情况下,则不起作用,节约资源。

2、启用磁盘锁。

由于两个active会争抢资源,导致从节点不知道该连接哪一台namenode,可以使用磁盘锁的形式,保证集群中只能有一台namenode获取磁盘锁,对外提供服务,避免数据错乱的情况发生。但是,也会存在一个问题,若该namenode节点宕机,则不能主动释放锁,那么其他的namenode就永远获取不了共享资源。因此,在HA上使用"智能锁"就成为了必要措施。"智能锁"是指active的namenode检测到了心跳线全部断开时才启动磁盘锁,正常情况下不上锁。保证了假死状态下,仍然只有一台namenode的节点提供服务。

3、设置仲裁机制

脑裂导致的后果最主要的原因就是从节点不知道该连接哪一台namenode,此时如果有一方来决定谁留下,谁放弃就最好了。因此出现了仲裁机制,比如提供一个参考的IP地址,当出现脑裂现象时,双方接收不到对方的心跳机制,但是能同时ping参考IP,如果有一方ping不通,那么表示该节点网络已经出现问题,则该节点需要自行退出争抢资源的行列,或者更好的方法是直接强制重启,这样能更好的释放曾经占有的共享资源,将服务的提供功能让给功能更全面的namenode节点。

以上的3种方式可以同时使用,这样更能减少集群中脑裂情况的发生。但是还是不能保证完全不出现,如果仲裁机制中2台机器同时宕机,那么此时集群中没有namenode可以使用。此时需要运维人员人工的抢修,或者提供一台新的机器作为namenode,这个时间是不可避免的。希望未来能有更好的解决办法,能彻底杜绝这类情况的发生吧~

Zookeeper选举算法原理的更多相关文章

  1. zookeeper选举算法

    一.ZAB协议三阶段 – 发现(Discovery),即选举Leader过程– 同步(Synchronization),选举出新的Leader后,Follwer或者Observer从Leader同步最 ...

  2. 【原创】大数据基础之Zookeeper(3)选举算法

    提到zookeeper选举算法,就不得不提Paxos算法,因为zookeeper选举算法是Paxos算法的一个变种: Paxos要解决的问题是:在一个分布式网络环境中有众多的参与者,但是每个参与者都不 ...

  3. Zookeeper的选举算法和脑裂问题

    ZK介绍 ZK = zookeeper ZK是微服务解决方案中拥有服务注册发现最为核心的环境,是微服务的基石.作为服务注册发现模块,并不是只有ZK一种产品,目前得到行业认可的还有:Eureka.Con ...

  4. zookeeper选举原理

    zookeeper的领导者选举和原子广播   目录:     1.工作原理概述     2.Fast Leader选举算法(领导者选举)     3.Leader与Follower同步数据(原子广播) ...

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

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

  6. Zookeeper笔记(二)Paxos算法与Zookeeper的工作原理

    Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管 ...

  7. Zookeeper实现分布式选举算法

    分布式系统中经常采用Master/Slave架构.(截止到目前为止我还没有碰到过其他架构...)这种架构中如果Master发生故障就会导致整个集群停止服务,为了提高系统的高可用性通常采用选举算法来选出 ...

  8. 图解zookeeper FastLeader选举算法

    zookeeper当配置为群集模式,在启动或异常情况将被选举为的例子Leader.默认选择算法FastLeaderElection. 不知道zookeeper够考虑这样一个问题:某个服务能够配置为多个 ...

  9. 图解zookeeper FastLeader选举算法【转】

    转自:http://codemacro.com/2014/10/19/zk-fastleaderelection/ zookeeper配置为集群模式时,在启动或异常情况时会选举出一个实例作为Leade ...

随机推荐

  1. OpenCV源码解析

    OpenCV K-means源码解析 OpenCV 图片读取源码解析 OpenCV 视频播放源码解析 OpenCV 追踪算法源码解析 OpenCV SIFT算法源码解析 OpenCV 滤波源码分析:b ...

  2. 设计模式14:Command 命令模式(行为型模式)

    Command 命令模式(行为型模式) 耦合与变化 耦合是软件不能抵御变化的根本性原因.不仅实体对象与实体对象之间存在耦合关系,实体对象与行为操作之间也存在耦合关系. 动机(Motivation) 在 ...

  3. javascript 多个frame之间的交互

    主页面 Web.html  (加载了两个frame 分别为A.html) <html lang="en"> <head> <meta charset= ...

  4. 【图解HTTP】第二章 简单的http协议

    简单的HTTP协议 针对HTTP协议结构进行讲解,主要使用HTTP/1.1版本. HTTP协议用于客户端和服务器端之间的通信 通过请求和响应的交换达成通信(从客户端开始建立通信,服务器端在没有接收到请 ...

  5. Linux删除(清空)正在运行的应用日志文件内容

    在测试环境定位问题时,如果发现日志文件内容太多或太大,有时需要删除该日志,如Tomcat,Nginx日志.以前每次都是先rm -rf ***.log,然后重启应用.直到后来发现了以下命令,原来可以不用 ...

  6. 小试maven工程

    由于工作中要用到maven来进行开发j2ee开发,所以选用了集成maven的eclipse版本: 下载地址: https://www.eclipse.org/downloads/ 根据提示下载32或者 ...

  7. DELPHI XE5-8 弹出列表框供选择

    点击章节练习: var tmplm:Tlistboxitem; begin dm.FDQTMP.SQL.Clear; dm.FDQTMP.SQL.Add('select GSESSON from TS ...

  8. cocos2dx conversion to dalvik format failed

    标题的这个问题不知道有没有朋友遇到过,我就被害惨了一个晚上加一个早上的时间了. 可能其他朋友很多搜conversion to dalvik format failed 都会看到一样的答案,我是针对做c ...

  9. ArcGIS Runtime SDK for Android 授权(arcgis android 去除水印)

    ArcGIS Runtime SDK for Android 授权 ESRI中国北京 要下载和安装 ArcGIS Runtime SDK for Android,您需要注册开发者账户,进而便拥有了访问 ...

  10. Mathcad操作tips:函数、符号计算

    函数 1. 利用“:”进行函数定义,如 2. 函数支持range variable输入,如 3. 常用数学函数可以在Insert - Function菜单中寻得. 4. 当不确定某个名字是否是函数名时 ...