面试官:说一下Zookeeper的ZAB协议?

文章来源于公众号三太子敖丙 ,作者严浩

前言

Zab(Zookeeper Atomic Broadcast)是为ZooKeeper协设计的崩溃恢复原子广播协议,它保证zookeeper集群数据的一致性和命令的全局有序性。

概念介绍

在介绍zab协议之前首先要知道zookeeper相关的几个概念,才能更好的了解zab协议。

  • 集群角色
  1. Leader:同一时间集群总只允许有一个Leader,提供对客户端的读写功能,负责将数据同步至各个节点;
  2. Follower:提供对客户端读功能,写请求则转发给Leader处理,当Leader崩溃失联之后参与Leader选举;
  3. Observer:与Follower不同的是但不参与Leader选举。
  • 服务状态
  1. LOOKING:当节点认为群集中没有Leader,服务器会进入LOOKING状态,目的是为了查找或者选举Leader;
  2. FOLLOWING:follower角色;
  3. LEADING:leader角色;
  4. OBSERVING:observer角色;

可以知道Zookeeper是通过自身的状态来区分自己所属的角色,来执行自己应该的任务。

  • ZAB状态Zookeeper还给ZAB定义的4中状态,反应Zookeeper从选举到对外提供服务的过程中的四个步骤。状态枚举定义:
public enum ZabState {
        ELECTION,
        DISCOVERY,
        SYNCHRONIZATION,
        BROADCAST
    }
  1. ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
  2. DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
  3. SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
  4. BROADCAST:过渡到广播状态,集群开始对外提供服务。
  • ZXID

Zxid是极为重要的概念,它是一个long型(64位)整数,分为两部分:纪元(epoch)部分和计数器(counter)部分,是一个全局有序的数字。

epoch代表当前集群所属的哪个leader,leader的选举就类似一个朝代的更替,你前朝的剑不能斩本朝的官,用epoch代表当前命令的有效性,counter是一个递增的数字。

选举

基础概念介绍完了,下面开始介绍zab协议是怎么支持leader选举的。

进行leader有三个问题,什么时候进行?选举规则?选择流程?

下面我会一一解答这三个问题:

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

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

  2. 选举规则进入投票选举流程,怎么才能选举出leader?或者说按照什么规则来让其他节点都能选举你当leader。

  3. 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)))));

当其他节点的纪元比自身高投它,如果纪元相同比较自身的zxid的大小,选举zxid大的节点,这里的zxid代表节点所提交事务最大的id,zxid越大代表该节点的数据越完整。

最后如果epoch和zxid都相等,则比较服务的serverId,这个Id是配置zookeeper集群所配置的,所以我们配置zookeeper集群的时候可以把服务性能更高的集群的serverId配置大些,让性能好的机器担任leader角色。

  1. 选举流程

时机和规则都有了,下面就是leader的选举流程:
image
  • 所有节点第一票先选举自己当leader,将投票信息广播出去;
  • 从队列中接受投票信息;
  • 按照规则判断是否需要更改投票信息,将更改后的投票信息再次广播出去;
  • 判断是否有超过一半的投票选举同一个节点,如果是选举结束根据投票结果设置自己的服务状态,选举结束,否则继续进入投票流程。
  1. 举例
    image

上图来自《ZooKeeper:分布式过程协同技术详解》,整体流程还是比较简单,这里就不具体分析了。

广播

集群在经过leader选举之后还会有连接leader和同步两个步骤,这里就不具体分析这两个步骤的流程了,主要介绍集群对外提供服务如何保证各个节点数据的一致性。

zab在广播状态中保证以下特征

  • 可靠传递: 如果消息m由一台服务器传递,那么它最终将由所有服务器传递。
  • 全局有序: 如果一个消息a在消息b之前被一台服务器交付,那么所有服务器都交付了a和b,并且a先于b。
  • 因果有序: 如果消息a在因果上先于消息b并且二者都被交付,那么a必须排在b之前。

有序性是zab协议必须要保证的一个很重要的属性,因为zookeeper是以类似目录结构的数据结构存储数据的,必须要求命名的有序性。

比如一个命名a创建路径为/test,然后命名b创建路径为/test/123,如果不能保证有序性b命名在a之前,b命令会因为父节点不存在而创建失败。
image

如上图所示,整个写请求类似一个二阶段的提交。

当收到客户端的写请求的时候会经历以下几个步骤:

  1. Leader收到客户端的写请求,生成一个事务(Proposal),其中包含了zxid;
  2. Leader开始广播该事务,需要注意的是所有节点的通讯都是由一个FIFO的队列维护的;
  3. Follower接受到事务之后,将事务写入本地磁盘,写入成功之后返回Leader一个ACK;
  4. Leader收到过半的ACK之后,开始提交本事务,并广播事务提交信息
  5. 从节点开始提交本事务。

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

zab协议的有序性保证是通过几个方面来体现的,第一是,服务之前用TCP协议进行通讯,保证在网络传输中的有序性;第二,节点之前都维护了一个FIFO的队列,保证全局有序性;第三,通过全局递增的zxid保证因果有序性。

状态流转

前面介绍了zookeeper服务状态有四种,ZAB状态也有四种。这里就简单介绍一个他们之间的状态流转,更能加深对zab协议在zookeeper工作流程中的作用。
image
  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协议就是驱动服务状态流转的关键,理解了zab就理解了zookeeper工作的关键原理

总结

本文对zab协议在zookeeper的工作流程中做了简单的介绍,希望对大家理解学习zookeeper有所帮助。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339