热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【zookeeper】zookeeper的ZAB协议

文章目录一、前言二、ZAB概要2.1ZAB定义ZAB作用Zxid2.2Zookeeper集群中的三个角色(重点:leaderfollowerobserv


文章目录

  • 一、前言
  • 二、ZAB概要
    • 2.1 ZAB定义 + ZAB作用 + Zxid
    • 2.2 Zookeeper集群中的三个角色(重点:leader follower observer)
      • 2.2.1 三个角色:leader follower observer
      • 2.2.2 三个角色:选举阶段 + 广播阶段
      • 2.2.2 observer存在的意义 + leader存在的意义 + follower存在的意义
    • 2.3 Zookeeper四种状态 + ZAB四种状态
      • 2.3.1 Zookeeper集群的服务状态:四种
      • 2.3.2 ZAB状态:四种
  • 三、Zookeeper选举过程(基于ZAB协议)
    • 3.1 when何时,leader选举的两个时机
    • 3.2 how理论上,leader选举的三种选举规则
    • 3.3 how实践上,leader选举的选举流程:四个步骤
  • 四、Zookeeper的广播过程(读写操作)
    • 4.1 ZAB协议有序性
    • 4.2 基础知识:两阶段提交(为zookeeper阶段准备)
    • 4.3 一个写请求的两阶段提交流程
  • 五、四个状态流转(zookeeper四种服务状态 + ZAB四种步骤状态)
  • 六、面试金手指
    • 6.1 起手式,ZAB + Zookeeper 基础
      • 6.1.1 ZAB定义 + ZAB作用 + Zxid
      • 6.1.2 Zookeeper集群中的三个角色(重点:leader follower observer)
        • 6.1.2.1 三个角色:leader follower observer
        • 6.1.2.2 三个角色:选举阶段 + 广播阶段
        • 6.1.2.3 observer存在的意义 + leader存在的意义 + follower存在的意义
    • 6.2 Zookeeper的选举过程
    • 6.3 Zookeeper的广播过程
      • 6.3.1 ZAB协议有序性
      • 6.3.2 基础知识:两阶段提交(为zookeeper阶段准备)
      • 6.3.3 一个写请求的两阶段提交流程
    • 6.4 Zookeepr四状态 + ZAB四状态
  • 七、小结


一、前言


二、ZAB概要


2.1 ZAB定义 + ZAB作用 + Zxid


ZAB定义:ZAB 英文全称为 Zookeeper Atomic Broadcast,译为 Zookeeper 原子广播协议;
ZAB作用:当ZooKeeper leader节点宕机时,用于崩溃恢复的原子广播协议,它保证了zookeeper集群的 数据一致性命令全局有序性



注意两个关键字:数据一致性 和 命令全局有序性,下面介绍,当leader节点宕机的时候,是怎样保证数据一致性和 命令全全局有序性的。



ZXID(64bit) = epoch(32bit) + counter(32bit)
Zxid定义:Zxid是一个long型(64位)整数,分为两部分:纪元(epoch)部分和计数器(counter)部分,是一个全局有序的数字。
epoch定义:epoch表示当前集群所属的哪个leader,leader的选举就类似一个朝代的更替,你前朝的剑不能斩本朝的官,用epoch代表当前命令的有效性。
counter定义:counter是一个递增的数字。



2.2 Zookeeper集群中的三个角色(重点:leader follower observer)


2.2.1 三个角色:leader follower observer

Leader:同一时间集群总只允许有一个Leader,提供对客户端的读写功能,负责将数据同步至各个节点;
Follower:提供对客户端读功能,写请求则转发给Leader处理,当Leader崩溃失联之后参与Leader选举;
Observer:与Follower不同的是但不参与Leader选举。


2.2.2 三个角色:选举阶段 + 广播阶段


zookeeper集群三个角色注意(选举阶段)
关于leader,有且只有一个,没有(启动没有/有了宕机)就选举,有了不需要了。
关于follower,在两种情况的选举下,拥有 投票权(可以贡献一票) 和 被选举权(可能被选举为leader)。
关于observer,在两种情况的选举下,无 投票权(无法贡献一票) 和 被选举权 (不可能被选举为leader)。
所有说,当leader不存在的时候(启动/宕机),是所有的follower来投票,是从follower中选举出一个超过半数follower同意的follower,来成为leader。所以,整个选举过程,和observer 没半毛钱关闭。



zookeeper集群三个角色注意(广播阶段)
关于leader,有且只有一个,用来处理写请求,是zookeeper集群中唯一一个处理请求的节点。
关于follower,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段所有follower投票过半即可
关于observer,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段投票没observer什么事。



所以说,由于observer没有 投票权 和 被选举权,选举时的过半数通过和写操作时的过半数ACK 都和它没关系,都是follower和leader的事。



比喻:leader是项目经理(技术攻关写请求)、follower是正式员工(平时干活读请求,投票和被选举)、observer是外包员工(平时干活读请求,无投票、无被选举)



2.2.2 observer存在的意义 + leader存在的意义 + follower存在的意义


问题:observer存在的意义(选举过程中,和observer没半毛钱关系,为什么需要observer)?
标准答案:增加observer节点,在不影响吞吐量的情况下,增加伸缩性;
增加follower阶段,在影响吞吐量的情况下,增加伸缩性。
解释:Zookeeper 需保证高可用和强一致性,为了支持更多的客户端,需要增加更多 Server;
Server包括两种,follower和observer(其实,leader也是Server,但是只有一个)
follower 增多,投票阶段延迟增大,影响性能(影响吞吐量);引入一种不参与投票的follower,就是observer,因为不参与投票(投票是一种延迟大的内部消耗),所以完全用来处理用户连接; Observers 接受客户端的连接,并将写请求转发给 leader 节点; 加入更多 Observer 节点,提高伸缩性,同时不影响吞吐率。



问题:leader存在的意义(为什么需要一个leader,为什么需要投票选举一个leader,投票是一个延迟大的内部消耗,为什么不去掉)
标准答案:
1、集群server的数据一致性:zookeeper是一个集群,集群是由多个server组成的,多个server要保证数据一致性,这是集群的要求,无法改变。
2、主从结构:然后,要保证多个server的数据一致性,就要灵活处理好 读写请求,就要做 主从结构,主从结构处理的两种方式
(1)主写从读,类似mysql集群读写分离,主库处理写请求(insert|update|delete),从库读(select),然后按时间间隔使用binlog日志将主库中的数据同步到从库,保证读到的数据是刚刚写入的(从库加入时,第一次根据binlog全量复制主库,以后根据binlog增量复制主库数据变化即可);优点:这一种方式,主库和从库,每个数据库都运用起来的,最大化集群吞吐量。
(2)主读写,从仅同步,类似kafka中的,kafka本身就是基于分布式架构的(不用像mysql额外做分布式),partition分区,部署在三个以上的broker中,生产消息和消费消息都在主partition,从partition仅仅同步,当主partition宕机后,才开始操作。
zookeeper使用的时类似mysql集群的,
对于写操作:所有的写操作必须要通过 Leader 完成再由 Leader 将写操作广播给其它服务器,只要有超过半数节点(不包括 observer 节点)写入成功,该写请求就会被提交(类 2PC 协议)。
对于读操作:follower和observer 都可以直接处理并返回客户端的读请求,但是都会将 写请求转发给 Leader 处理。



问题:follower存在的意义(为什么需要一个follower)
标准答案:zookeeper 是分布式架构,follower是最基本的节点,具有 投票权 和 被选举权,唯一的leader节点从follower节点产生(observer没有被选举权,不可能变为leader)
至于observer,是没有 投票权 和 被选举权的 follower,增加observer节点,在不影响吞吐量的情况下,增加伸缩性。



2.3 Zookeeper四种状态 + ZAB四种状态


2.3.1 Zookeeper集群的服务状态:四种

LOOKING:当节点认为群集中没有Leader,服务器会进入LOOKING状态,目的是为了查找或者选举Leader;
FOLLOWING:follower角色;
LEADING:leader角色;
OBSERVING:observer角色;
可以知道Zookeeper是通过自身的状态来区分自己所属的角色,来执行自己应该的任务。


金手指:从 “zookeeper分为选主阶段和广播阶段” 看 zookeeper 的四个状态和 ZAB 的四个状态
对于zookeeper的四个状态
looking仅在选主阶段出现
following是zookeeper在广播阶段的follower节点的状态,
leading是zookeeper在广播阶段的leader节点的状态,
observing是zookeeper在广播阶段的observer节点的状态。
对于ZAB的四个状态,实际上选主阶段的四种过程
ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
BROADCAST:过渡到广播状态,集群开始对外提供服务。



2.3.2 ZAB状态:四种


Zookeeper给ZAB定义了四种状态,与Zookeeper的四种状态对应,下面有图解


ZAB状态作用:反应Zookeeper从选举到对外提供服务的过程中的四个步骤。

ZAB状态定义(枚举定义):ELECTION、DISCOVERY、SYNCHRONIZATION、BROADCAST

public enum ZabState {ELECTION,DISCOVERY,SYNCHRONIZATION,BROADCAST
}

ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
BROADCAST:过渡到广播状态,集群开始对外提供服务。


三、Zookeeper选举过程(基于ZAB协议)


zookeeper集群中,leader选举基于ZAB协议
zookeeper集群中,只能有一个leader节点,这个leader节点的选举(zookeeper启动时选举leader、leader宕机后选举leader)是基于zab协议来完成的。



zookeeper集群中,leader选举三个问题,
第一,when何时:leader选举什么时候进行?zookeeper启动的时候从follower中选举leader + 原有leader宕机后从follower中选举leader.
第二,how理论上,选举规则?
第三,how实践上,选择流程?



3.1 when何时,leader选举的两个时机

选举发生的时机Leader发生选举有两个时机:

1、zookeeper服务启动的时候当整个集群都没有leader节点会进入选举状态,如果leader已经存在就会告诉该节点leader的信息,自己连接上leader,整个集群不用进入选举状态。

2、zookeeper服务运行中,可能会出现各种情况,服务宕机、断电、网络延迟很高的时候leader都不能再对外提供服务了,所有当其他几点通过心跳检测到leader失联之后,集群也会进入选举状态。


3.2 how理论上,leader选举的三种选举规则

接上面,达到两种选举时机之一,开始选举。

zab协议是按照几个比较规则来进行投票的筛选,如果你的票比我更好,就修改自身的投票信息,改投你当leader。

下面代码是zookeeper投票比较规则:

/** 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)))));

对应上面代码的解释(两个节点之间使用比较的方法来选举,三种比较规则):
1、比较 epoche纪元(zxid高32bit),如果其他节点的纪元比自己的大,选举 epoch大的节点(理由:epoch 表示年代,epoch越大表示数据越新)代码:(newEpoch > curEpoch);
2、比较 zxid, 如果纪元相同,就比较两个节点的zxid的大小,选举 zxid大的节点(理由:zxid 表示节点所提交事务最大的id,zxid越大代表该节点的数据越完整)代码:(newEpoch == curEpoch) && (newZxid > curZxid);
3、比较 serviceId,如果 epoch和zxid都相等,就比较服务的serverId,选举 serviceId大的节点(理由: serviceId 表示机器性能,他是在配置zookeeper集群时确定的,所以我们配置zookeeper集群的时候可以把服务性能更高的集群的serverId设置大些,让性能好的机器担任leader角色)代码 :(newEpoch == curEpoch) && ((newZxid == curZxid) && (newId > curId))。



3.3 how实践上,leader选举的选举流程:四个步骤

在这里插入图片描述


对于上图的解释(leader选举的):
步骤1(每个节点第一个先选自己):所有节点第一票先选举自己当leader,将投票信息广播出去;
步骤2(每个节点接受其他 n-1 个节点):从队列中接受投票信息;
步骤3(根据三个比较规则,确定自己选举的leader,然后第二次广播出去):按照三条规则判断是否需要更改投票信息,将更改后的投票信息再次广播出去;
步骤4:(是否一个节点过半数,是了就行了,不是跳到步骤2,继续接收 n-1 节点)判断是否有超过一半的投票选举同一个节点,如果是选举结束根据投票结果设置自己的服务状态,选举结束,否则继续进入投票流程。



问题:为什么zookeeper选举过程设计为一半通过?为什么不是 1/3 投票 或者 2/3 投票?
第一,为什么不是1/3而是1/2?标准答案:为了确保leader的唯一性,一个follower节点获得了1/2票数,就不可能再有一个follower节点或者 1/2 票数,就唯一确定了这个follower为leader;如果设置为1/3,选出两个follower达到 1/3 票数,但是leader只有一个,选谁,还是要继续比较票数吗?太麻烦,还不如设置为 1/2 ,一步到位;同理,设置 1/4,选出 三个 follower大于 1/4,尴尬…
第二,为什么不是2/3而是1/2?标准答案:节约选举成本,投票是一种延迟大的内部消耗,影响吞吐量,这就是为什么要引入 无投票权、无被选举权的 observer的原因,1/2已经能够确定唯一的leader,变为2/3 3/4 只会加大选举的循环次数,影响性能。
问题:为什么zookeeper写操作设计为一半ACK?为什么不是 1/3 ACK 或者 2/3 ACK ?
标准答案:没有什么太大理由,zookeeper就是这么设计,所以说zookeeper是非强一致性的,二阶段提交,第二阶段follower ACK数量过半就行(Ack确定和observer无关,无论是哪个节点 leader/follower/observer 收到写操作,都是发送给leader,follower过半ACK,leader就提交)。



关于zookeeper中的投票过半数(包含两层意思):
第一,选举过程中,一半的节点选举了,就好了
第二,广播过程中,两阶段提交,eader收到一半的follower发过来的ACK,就提交了(所以,zookeeper不是强一致性的)

问题:为什么说zookeeper的两阶段提交不是强一致性的?
回答:之前的mysql和oracle基于XA实现的分布式事务,底层两阶段提交是要所有的都ACK,三阶段提交也是要所有的都ACK,这才是强一致性的。



四、Zookeeper的广播过程(读写操作)


zookeeper集群对外提供服务(即读写操作)如何保证各个节点数据的一致性。



4.1 ZAB协议有序性


有序性定义? + ZAB保证有序性实现?
有序性定义?
标准答案
:zab在广播状态中保证以下特征
第一,可靠传递: 如果消息m由一台服务器传递,那么它最终将由所有服务器传递。
第二,全局有序: 如果一个消息a在消息b之前被一台服务器交付,那么所有服务器都交付了a和b,并且a先于b。
第三,因果有序: 如果消息a在因果上先于消息b并且二者都被交付,那么a必须排在b之前。
ZAB保证有序性实现?
标准答案
:zab协议的有序性保证是通过几个方面来体现的,
第一,服务之前用TCP协议进行通讯,保证在网络传输中的有序性;
第二,节点之前都维护了一个FIFO的队列,保证全局有序性;
第三,通过全局递增的zxid保证因果有序性。



为什么需要zab需要保证有序性?
标准答案
:zookeeper的存储结构是类型目录结构,不保证有序性无法定位,会报错。
有序性是zab协议必须要保证的一个很重要的属性,因为zookeeper是以类似目录结构的数据结构存储数据的,必须要求命名的有序性。比如一个命名a创建路径为/test,然后命名b创建路径为/test/123,如果不能保证有序性b命名在a之前,b命令会因为父节点不存在而创建失败。



4.2 基础知识:两阶段提交(为zookeeper阶段准备)


基础知识:两阶段提交(定义 + 流程 + 优缺点)
两阶段提交定义:在分布式系统中,每一个机器节点虽然能够明确的知道自己在进行事物操作过程的结果是失败或成功,但却无法直接获取其他分布式节点的操作结果,所以,事物操作需要跨越多个分布式节点的时候,需要引入一个协调者统一调度所有节点的执行逻辑。
两阶段提交详细:
阶段一:提交事物请求
1.1 leader事物询问
协调者向所有的参与者发送事物内容,询问是否可以执行事物操作,并开始等待各参与者的响应。
1.2 follower/observer执行事物
各参与者节点执行事物操作,并将Undo和Redo信息记入事物日志中
1.3 各参与者follower/observer向协调者leader反馈事物询问的响应
如果参与者成功执行了事物操作,那么就反馈给协调者Yes响应,表示事物可以执行;如果参与者没有成功执行事物,那么就反馈给协调者No响应,表示事物不可以执行。
阶段二:执行事物请求
在阶段二中协调者会根据参与者的反馈情况来决定最终是否可以进行事物操作,其中有两种可能 Commit/Cancel。假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事物响应(zookeeper是过半就好)。
2.1 Leader发送提交请求
协调者向所有参与者节点发出Commit请求
2.2 follower/observer事物提交
参与者接收到Commit请求后,会正式执行事物提交操作,并在完成提交之后释放在整个事物执行期间占有的事物资源。
2.3 follower/observer反馈事物提交结果
参与者在完成事物提交之后,向协调者发送Ack消息。
2.4 leader完成事物
协调者接收到所有参与者反馈的Ack消息后,完成事物。
二阶段提交优缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,脑裂,数据丢失(四个问题,在分布式事务中讲到过)。



4.3 一个写请求的两阶段提交流程

在这里插入图片描述


解释上图(zookeeper写请求的两阶段提交):
当收到客户端的写请求的时候会经历以下几个步骤:
步骤1(阶段一,Leader发出):Leader收到客户端的写请求,生成一个事务(Proposal),其中包含了zxid;
步骤2(阶段一,Leader发出):Leader开始广播该事务,需要注意的是所有节点的通讯都是由一个FIFO的队列维护的;
步骤3(阶段一,Leader发出):Follower接受到事务之后,将事务写入本地磁盘,写入成功之后返回Leader一个ACK;
步骤4(阶段二,Leader接收):Leader收到过半的ACK之后,开始提交本事务,并广播事务提交Commit信息
步骤5(阶段二,Leader接收):从节点开始提交本事务。


所以,zookeeper通过二阶段提交来保证集群中数据的一致性,因为只需要收到过半的ACK就可以提交事务,所以zookeeper的数据并不是强一致性。


五、四个状态流转(zookeeper四种服务状态 + ZAB四种步骤状态)

前面介绍了zookeeper服务状态有四种,ZAB状态也有四种。这里就简单介绍一个他们之间的状态流转,更能加深对zab协议在zookeeper工作流程中的作用。

在这里插入图片描述


对于上图的解释:
步骤1:服务在启动或者和leader失联之后服务状态转为LOOKING;
步骤2:如果leader不存在选举leader,如果存在直接连接leader,此时zab协议状态为ELECTION;
步骤3:如果有超过半数的投票选择同一台server,则leader选举结束,被选举为leader的server服务状态为LEADING,其他server服务状态为FOLLOWING/OBSERVING;
步骤4:所有server连接上leader,此时zab协议状态为DISCOVERY;
步骤5:leader同步数据给learner,使各个从节点数据和leader保持一致,此时zab协议状态为SYNCHRONIZATION;
步骤6:同步超过一半的server之后,集群对外提供服务,此时zab状态为BROADCAST。


所以,zookeeper服务的工作流程类似一个状态机的转换,而zab协议就是驱动服务状态流转的关键。


六、面试金手指


6.1 起手式,ZAB + Zookeeper 基础


6.1.1 ZAB定义 + ZAB作用 + Zxid


ZAB定义:ZAB 英文全称为 Zookeeper Atomic Broadcast,译为 Zookeeper 原子广播协议;
ZAB作用:当ZooKeeper leader节点宕机时,用于崩溃恢复的原子广播协议,它保证了zookeeper集群的 数据一致性命令全局有序性



ZXID(64bit) = epoch(32bit) + counter(32bit)
Zxid定义:Zxid是一个long型(64位)整数,分为两部分:纪元(epoch)部分和计数器(counter)部分,是一个全局有序的数字。
epoch定义:epoch表示当前集群所属的哪个leader,leader的选举就类似一个朝代的更替,你前朝的剑不能斩本朝的官,用epoch代表当前命令的有效性。
counter定义:counter是一个递增的数字。



6.1.2 Zookeeper集群中的三个角色(重点:leader follower observer)


6.1.2.1 三个角色:leader follower observer


Leader:同一时间集群总只允许有一个Leader,提供对客户端的读写功能,负责将数据同步至各个节点;
Follower:提供对客户端读功能,写请求则转发给Leader处理,当Leader崩溃失联之后参与Leader选举;
Observer:与Follower不同的是但不参与Leader选举。



6.1.2.2 三个角色:选举阶段 + 广播阶段


zookeeper集群三个角色注意(选举阶段)
关于leader,有且只有一个,没有(启动没有/有了宕机)就选举,有了不需要了。
关于follower,在两种情况的选举下,拥有 投票权(可以贡献一票) 和 被选举权(可能被选举为leader)。
关于observer,在两种情况的选举下,无 投票权(无法贡献一票) 和 被选举权 (不可能被选举为leader)。
所有说,当leader不存在的时候(启动/宕机),是所有的follower来投票,是从follower中选举出一个超过半数follower同意的follower,来成为leader。所以,整个选举过程,和observer 没半毛钱关闭。



zookeeper集群三个角色注意(广播阶段)
关于leader,有且只有一个,用来处理写请求,是zookeeper集群中唯一一个处理请求的节点。
关于follower,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段所有follower投票过半即可
关于observer,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段投票没observer什么事。



所以说,由于observer没有 投票权 和 被选举权,选举时的过半数通过和写操作时的过半数ACK 都和它没关系,都是follower和leader的事。



比喻:leader是项目经理(技术攻关写请求)、follower是正式员工(平时干活读请求,投票和被选举)、observer是外包员工(平时干活读请求,无投票、无被选举)



6.1.2.3 observer存在的意义 + leader存在的意义 + follower存在的意义


问题:observer存在的意义(选举过程中,和observer没半毛钱关系,为什么需要observer)?
标准答案:增加observer节点,在不影响吞吐量的情况下,增加伸缩性;
增加follower阶段,在影响吞吐量的情况下,增加伸缩性。
解释:Zookeeper 需保证高可用和强一致性,为了支持更多的客户端,需要增加更多 Server;
Server包括两种,follower和observer(其实,leader也是Server,但是只有一个)
follower 增多,投票阶段延迟增大,影响性能(影响吞吐量);引入一种不参与投票的follower,就是observer,因为不参与投票(投票是一种延迟大的内部消耗),所以完全用来处理用户连接; Observers 接受客户端的连接,并将写请求转发给 leader 节点; 加入更多 Observer 节点,提高伸缩性,同时不影响吞吐率。



问题:leader存在的意义(为什么需要一个leader,为什么需要投票选举一个leader,投票是一个延迟大的内部消耗,为什么不去掉)
标准答案:
1、集群server的数据一致性:zookeeper是一个集群,集群是由多个server组成的,多个server要保证数据一致性,这是集群的要求,无法改变。
2、主从结构:然后,要保证多个server的数据一致性,就要灵活处理好 读写请求,就要做 主从结构,主从结构处理的两种方式
(1)主写从读,类似mysql集群读写分离,主库处理写请求(insert|update|delete),从库读(select),然后按时间间隔使用binlog日志将主库中的数据同步到从库,保证读到的数据是刚刚写入的(从库加入时,第一次根据binlog全量复制主库,以后根据binlog增量复制主库数据变化即可);优点:这一种方式,主库和从库,每个数据库都运用起来的,最大化集群吞吐量。
(2)主读写,从仅同步,类似kafka中的,kafka本身就是基于分布式架构的(不用像mysql额外做分布式),partition分区,部署在三个以上的broker中,生产消息和消费消息都在主partition,从partition仅仅同步,当主partition宕机后,才开始操作。
zookeeper使用的时类似mysql集群的,
对于写操作:所有的写操作必须要通过 Leader 完成再由 Leader 将写操作广播给其它服务器,只要有超过半数节点(不包括 observer 节点)写入成功,该写请求就会被提交(类 2PC 协议)。
对于读操作:follower和observer 都可以直接处理并返回客户端的读请求,但是都会将 写请求转发给 Leader 处理。



问题:follower存在的意义(为什么需要一个follower)
标准答案:zookeeper 是分布式架构,follower是最基本的节点,具有 投票权 和 被选举权,唯一的leader节点从follower节点产生(observer没有被选举权,不可能变为leader)
至于observer,是没有 投票权 和 被选举权的 follower,增加observer节点,在不影响吞吐量的情况下,增加伸缩性。



6.2 Zookeeper的选举过程


zookeeper集群中,leader选举基于ZAB协议
zookeeper集群中,只能有一个leader节点,这个leader节点的选举(zookeeper启动时选举leader、leader宕机后选举leader)是基于zab协议来完成的。



zookeeper集群中,leader选举三个问题,
第一,when何时:leader选举什么时候进行?
zookeeper启动的时候从follower中选举leader + 原有leader宕机后从follower中选举leader.
第二,how理论上,选举规则?
1、比较 epoche纪元(zxid高32bit),如果其他节点的纪元比自己的大,选举 epoch大的节点(理由:epoch 表示年代,epoch越大表示数据越新)代码:(newEpoch > curEpoch);
2、比较 zxid, 如果纪元相同,就比较两个节点的zxid的大小,选举 zxid大的节点(理由:zxid 表示节点所提交事务最大的id,zxid越大代表该节点的数据越完整)代码:(newEpoch == curEpoch) && (newZxid > curZxid);
3、比较 serviceId,如果 epoch和zxid都相等,就比较服务的serverId,选举 serviceId大的节点(理由: serviceId 表示机器性能,他是在配置zookeeper集群时确定的,所以我们配置zookeeper集群的时候可以把服务性能更高的集群的serverId设置大些,让性能好的机器担任leader角色)代码 :(newEpoch == curEpoch) && ((newZxid == curZxid) && (newId > curId))。
第三,how实践上,选举leader流程?
步骤1(每个节点第一个先选自己):所有节点第一票先选举自己当leader,将投票信息广播出去;
步骤2(每个节点接受其他 n-1 个节点):从队列中接受投票信息;
步骤3(根据三个比较规则,确定自己选举的leader,然后第二次广播出去):按照三条规则判断是否需要更改投票信息,将更改后的投票信息再次广播出去;
步骤4:(是否一个节点过半数,是了就行了,不是跳到步骤2,继续接收 n-1 节点)判断是否有超过一半的投票选举同一个节点,如果是选举结束根据投票结果设置自己的服务状态,选举结束,否则继续进入投票流程。



问题:为什么zookeeper选举过程设计为一半通过?为什么不是 1/3 投票 或者 2/3 投票?
第一,为什么不是1/3而是1/2?标准答案:为了确保leader的唯一性,一个follower节点获得了1/2票数,就不可能再有一个follower节点或者 1/2 票数,就唯一确定了这个follower为leader;如果设置为1/3,选出两个follower达到 1/3 票数,但是leader只有一个,选谁,还是要继续比较票数吗?太麻烦,还不如设置为 1/2 ,一步到位;同理,设置 1/4,选出 三个 follower大于 1/4,尴尬…
第二,为什么不是2/3而是1/2?标准答案:节约选举成本,投票是一种延迟大的内部消耗,影响吞吐量,这就是为什么要引入 无投票权、无被选举权的 observer的原因,1/2已经能够确定唯一的leader,变为2/3 3/4 只会加大选举的循环次数,影响性能。
问题:为什么zookeeper写操作设计为一半ACK?为什么不是 1/3 ACK 或者 2/3 ACK ?
标准答案:没有什么太大理由,zookeeper就是这么设计,所以说zookeeper是非强一致性的,二阶段提交,第二阶段follower ACK数量过半就行(Ack确定和observer无关,无论是哪个节点 leader/follower/observer 收到写操作,都是发送给leader,follower过半ACK,leader就提交)。



关于zookeeper中的投票过半数(包含两层意思):
第一,选举过程中,一半的节点选举了,就好了
第二,广播过程中,两阶段提交,eader收到一半的follower发过来的ACK,就提交了(所以,zookeeper不是强一致性的)

问题:为什么说zookeeper的两阶段提交不是强一致性的?
回答:之前的mysql和oracle基于XA实现的分布式事务,底层两阶段提交是要所有的都ACK,三阶段提交也是要所有的都ACK,这才是强一致性的。



6.3 Zookeeper的广播过程


6.3.1 ZAB协议有序性


有序性定义? + ZAB保证有序性实现?
有序性定义?
标准答案
:zab在广播状态中保证以下特征
第一,可靠传递: 如果消息m由一台服务器传递,那么它最终将由所有服务器传递。
第二,全局有序: 如果一个消息a在消息b之前被一台服务器交付,那么所有服务器都交付了a和b,并且a先于b。
第三,因果有序: 如果消息a在因果上先于消息b并且二者都被交付,那么a必须排在b之前。
ZAB保证有序性实现?
标准答案
:zab协议的有序性保证是通过几个方面来体现的,
第一,服务之前用TCP协议进行通讯,保证在网络传输中的有序性;
第二,节点之前都维护了一个FIFO的队列,保证全局有序性;
第三,通过全局递增的zxid保证因果有序性。



为什么需要zab需要保证有序性?
标准答案
:zookeeper的存储结构是类型目录结构,不保证有序性无法定位,会报错。
有序性是zab协议必须要保证的一个很重要的属性,因为zookeeper是以类似目录结构的数据结构存储数据的,必须要求命名的有序性。比如一个命名a创建路径为/test,然后命名b创建路径为/test/123,如果不能保证有序性b命名在a之前,b命令会因为父节点不存在而创建失败。



6.3.2 基础知识:两阶段提交(为zookeeper阶段准备)


基础知识:两阶段提交(定义 + 流程 + 优缺点)
两阶段提交定义:在分布式系统中,每一个机器节点虽然能够明确的知道自己在进行事物操作过程的结果是失败或成功,但却无法直接获取其他分布式节点的操作结果,所以,事物操作需要跨越多个分布式节点的时候,需要引入一个协调者统一调度所有节点的执行逻辑。
两阶段提交详细:
阶段一:提交事物请求
1.1 leader事物询问
协调者向所有的参与者发送事物内容,询问是否可以执行事物操作,并开始等待各参与者的响应。
1.2 follower/observer执行事物
各参与者节点执行事物操作,并将Undo和Redo信息记入事物日志中
1.3 各参与者follower/observer向协调者leader反馈事物询问的响应
如果参与者成功执行了事物操作,那么就反馈给协调者Yes响应,表示事物可以执行;如果参与者没有成功执行事物,那么就反馈给协调者No响应,表示事物不可以执行。
阶段二:执行事物请求
在阶段二中协调者会根据参与者的反馈情况来决定最终是否可以进行事物操作,其中有两种可能 Commit/Cancel。假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事物响应(zookeeper是过半就好)。
2.1 Leader发送提交请求
协调者向所有参与者节点发出Commit请求
2.2 follower/observer事物提交
参与者接收到Commit请求后,会正式执行事物提交操作,并在完成提交之后释放在整个事物执行期间占有的事物资源。
2.3 follower/observer反馈事物提交结果
参与者在完成事物提交之后,向协调者发送Ack消息。
2.4 leader完成事物
协调者接收到所有参与者反馈的Ack消息后,完成事物。
二阶段提交优缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,脑裂,数据丢失(四个问题,在分布式事务中讲到过)。



6.3.3 一个写请求的两阶段提交流程


zookeeper写请求的两阶段提交(当收到客户端的写请求的时候会经历以下几个步骤):
步骤1(阶段一,Leader发出):Leader收到客户端的写请求,生成一个事务(Proposal),其中包含了zxid;
步骤2(阶段一,Leader发出):Leader开始广播该事务,需要注意的是所有节点的通讯都是由一个FIFO的队列维护的;
步骤3(阶段一,Leader发出):Follower接受到事务之后,将事务写入本地磁盘,写入成功之后返回Leader一个ACK;
步骤4(阶段二,Leader接收):Leader收到过半的ACK之后,开始提交本事务,并广播事务提交Commit信息
步骤5(阶段二,Leader接收):从节点开始提交本事务。


所以,zookeeper通过二阶段提交来保证集群中数据的一致性,因为只需要收到过半的ACK就可以提交事务,所以zookeeper的数据并不是强一致性。


6.4 Zookeepr四状态 + ZAB四状态


金手指:从 “zookeeper分为选主阶段和广播阶段” 看 zookeeper 的四个状态和 ZAB 的四个状态
对于zookeeper的四个状态
looking仅在选主阶段出现
following是zookeeper在广播阶段的follower节点的状态,
leading是zookeeper在广播阶段的leader节点的状态,
observing是zookeeper在广播阶段的observer节点的状态。
对于ZAB的四个状态,实际上选主阶段的四种过程
ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
BROADCAST:过渡到广播状态,集群开始对外提供服务。



七、小结

zookeeper的ZAB协议,完成了。

天天打码,天天进步!!!


推荐阅读
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 分布式开源任务调度框架 TBSchedule 深度解析与应用实践
    本文深入解析了分布式开源任务调度框架 TBSchedule 的核心原理与应用场景,并通过实际案例详细介绍了其部署与使用方法。首先,从源码下载开始,详细阐述了 TBSchedule 的安装步骤和配置要点。接着,探讨了该框架在大规模分布式环境中的性能优化策略,以及如何通过灵活的任务调度机制提升系统效率。最后,结合具体实例,展示了 TBSchedule 在实际项目中的应用效果,为开发者提供了宝贵的实践经验。 ... [详细]
  • B站服务器故障影响豆瓣评分?别担心,阿里巴巴架构师分享预防策略与技术方案
    13日晚上,在视频观看高峰时段,B站出现了服务器故障,引发网友在各大平台上的广泛吐槽。这一事件导致了连锁反应,大量用户纷纷涌入A站、豆瓣和晋江等平台,给这些网站带来了突如其来的流量压力。为了防止类似问题的发生,阿里巴巴架构师分享了一系列预防策略和技术方案,包括负载均衡、弹性伸缩和容灾备份等措施,以确保系统的稳定性和可靠性。 ... [详细]
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 在当今的软件开发领域,分布式技术已成为程序员不可或缺的核心技能之一,尤其在面试中更是考察的重点。无论是小微企业还是大型企业,掌握分布式技术对于提升工作效率和解决实际问题都至关重要。本周的Java架构师实战训练营中,我们深入探讨了Kafka这一高效的分布式消息系统,它不仅支持发布订阅模式,还能在高并发场景下保持高性能和高可靠性。通过实际案例和代码演练,学员们对Kafka的应用有了更加深刻的理解。 ... [详细]
  • 本文详细介绍了如何安全地手动卸载Exchange Server 2003,以确保系统的稳定性和数据的完整性。根据微软官方支持文档(https://support.microsoft.com/kb833396/zh-cn),在进行卸载操作前,需要特别注意备份重要数据,并遵循一系列严格的步骤,以避免对现有网络环境造成不利影响。此外,文章还提供了详细的故障排除指南,帮助管理员在遇到问题时能够迅速解决,确保整个卸载过程顺利进行。 ... [详细]
  • Zookeeper作为Apache Hadoop生态系统中的一个重要组件,主要致力于解决分布式应用中的常见数据管理难题。它提供了统一的命名服务、状态同步服务以及集群管理功能,有效提升了分布式系统的可靠性和可维护性。此外,Zookeeper还支持配置管理和临时节点管理,进一步增强了其在复杂分布式环境中的应用价值。 ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 本文详细介绍了在 Oracle 数据库中使用 MyBatis 实现增删改查操作的方法。针对查询操作,文章解释了如何通过创建字段映射来处理数据库字段风格与 Java 对象之间的差异,确保查询结果能够正确映射到持久层对象。此外,还探讨了插入、更新和删除操作的具体实现及其最佳实践,帮助开发者高效地管理和操作 Oracle 数据库中的数据。 ... [详细]
author-avatar
周鑫先生_852
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有