咱们都知道 Zookeeper 是基于 ZAB 协议实现的,在介绍 ZAB 协议以前,先回顾一下 Zookeeper 的起源与发展。java
Zookeeper 到底是在什么样的时代背景下被提出?为了解决了哪些棘手的问题?面试
Zookeeper 最先起源于雅虎研究院的一个研究小组。当时,研究人员发现,在雅虎的不少大型系统基本都须要依赖一个相似的系统来进行分布式协调,可是这些系统都存在分布式单点问题,因此雅虎的开发人员就试图开发出一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。算法
因而,Zookeeper 就诞生了!数据库
Zookeeper 的出现不只解决了分布式系统下数据一致性的问题,并且经历过线上验证,不管是从性能、易用性、稳定性上来讲,都是工业级产品的标准。能够说在分布式系统中具备不可替代的核心地位,Hadoop、HBase、Storm 和 Solr 等大型分布式系统都已经将 Zookeeper 做为其核心组件,用于分布式协调。即使 Zookeeper 如此优秀,可是 Zookeeper 依然是免费且开源的,全世界成千上万的开发者都关注着它,陪同着一块儿成长和发展。缓存
做为一个开发者不管是为了应付面试、晋升仍是我的技术成长的须要,都须要对 Zookeeper 有所了解,而学习 Zookeeper 的关键就是理解其核心部分: 服务器
ZAB 协议, 全称(Zookeeper Atomic Broadcast)Zookeeper 原子消息广播协议。微信
它与 Paxos 相似,也是一种数据一致性的算法。网络
在 ZAB 协议的开发设计人员在协议设计之初并无要求 ZAB 具备很好的扩展性,最初只是为了雅虎公司内部哪些高吞吐量、低延迟、健壮、简单的分布式系统场景设计的。基于 ZAB 协议,Zookeeper 实现了一种主备模式的系统架构来保持集群中各副本之间数据的一致性,简单架构图以下:架构
Zookeeper 用一个单一的主进程来接收并处理客户端的全部事物请求,并采用 ZAB 的原子广播协议将服务器数据状态以事物 Proposal 的形式广播到全部的副本进程中去。这样的模式就保证了,在同一时刻只有一个主进程来广播服务器的状态更变,所以可以很好地处理客户端大量的并发请求,这在 ZAB 协议中叫:消息广播。并发
除此以外,在分布式环境中事物的执行顺序也会存在必定的前后关系,好比:事务 C 的写入须要依赖事务 B 的写入,而事务 B 写入须要依赖事务 A 写入。这种先后依赖的顺序也对 ZAB 协议提出了一个要求:ZAB 协议须要保证若是一个状态的变动被处理了,那么全部其依赖的状态变动都已经被提早处理了。也就是须要顺序执行。
另外除了能正常广播消息、消息的顺序执行,主进程也可能随时会由于断电、机器宕机等异常状况没法提供服务,所以,ZAB 协议还须要作到在当前主进程出现上述异常状况的时候依然可以正常工做,这在 ZAB 协议中叫:崩溃恢复。
因此整个 ZAB 协议须要具有的核心特性已经被描述出来了,处理事务的请求的方式能够简单理解为:
全部的事务请求必须由一个全局惟一的服务器来协调处理,这样的服务器叫:Leader 服务器。其余的服务器被称为 Follower 服务器。Leader 服务器将客户端事务请求转化成一个事务 Prososal(提议),并将改 Proposal 分发给集群中全部的 Follower 服务器。以后 Leader 服务器接收了正确的反馈后,那么 Leader 就会再次向全部的 Follower 服务器分发 Commit 消息,要求将前一个 Proposal 提交。
这就简单阐述了ZAB 协议中消息广播模式的部份内容。
ZAB 协议的包括两种模式:崩溃恢复、消息广播。
既然有两种模式,那 Zookeeper 集群何时进入奔溃恢复模式?何时进入消息广播模式呢?
在进入奔溃恢复模式时 Zookeeper 集群会进行 Leader 选举,通常有两种状况会发生选举:
选举出 Leader 服务器后,会进入消息广播模式,开始接收处理客户端的请求,前文已经描述,这里再也不赘述。
在深刻讲解 ZAB 协议的两个模式以前,先解释 Zookeeper 的几个相关概念,方便理解 ZAB 协议:
在前面提到 Zookeeper 的集群中的服务器有 Leader 和 Follower ,但实际在 ZAB 协议中 Zookeeper 有三种角色,分别是 Leader、Folower、Observer,它们的分工各有不一样:
Leader :负责整个Zookeeper 集群工做机制中的核心,主要工做有一下两个:
Follower :它是 Leader 的追随者,其主要工做有三个:
在知道了 Zookeeper 中有三种角色后,不经提问: Zookeeper 是如何知道本身目前是什么角色的呢?
在 ZAB 协议中定义:经过自身的状态来区分本身的角色的,在运行期间各个进程可能出现如下三种状态之一:
在组成 ZAB 协议的全部进程启动的时候,初始化状态都是 LOOKING 状态,此时进程组中不存在 Leader,选举以后才有,在进行选举成功后,就进入消息广播模式,此时 Zookeeper 集群中的角色状态就再也不是 LOOKING 状态。
前文咱们知道 zookeeper 消息有严格的因果关系,所以必须将每个事务请求按照前后顺序来进行排序与处理。那 Zookeeper 是如何保持请求处理的顺序的呢?其中很是关键的点就是 ZXID。
那 ZXID 到底是怎么发挥做用的呢?
Leader 服务器在接收到事务请求后,会为每一个事务请求生成对应的 Proposal 来进行广播,而且在广播事务 Proposal 以前,Leader 服务器会首先为这个事务 Proposal 分配一个全局单调递增的惟一 ID ,咱们称之为事务 ID(即 ZXID)。
ZXID 的设计也颇有特色,是一个全局有序的 64 位的数字,能够分为两个部分:
这里低 32 位 counter(计数器)单调递增还好理解,高 32 位 epoch(纪元)每次选举加 1 也许有些同窗就有疑问了,为何 epoch(纪元)每次选须要举加 1 ,它在整个 ZAB 协议中有什么做用?
咱们知道每当选举产生一个新的 Leader 服务器时生成一个新的 epoch(纪元)值,而在前文咱们知道,服务运行过程当中触发选举 Leader 的条件是:Leader 服务器的出现网络中断、奔溃退出、重启等异常状况,或者当集群中半数的服务器与该 Leader 服务器没法通讯时。
这说明整个 Zookeeper 集群此时处于一个异常的状况下,而在发生异常前,消息广播进行到哪一步骤咱们根本不知道,集群中的其余 Follower 节点从这种崩溃恢复状态从新选举出 Leader 后,若是老 Leader 又恢复了链接进入集群。此时老 Leader 的 epoch 确定会小于新 Leader 的 epoch,这时就将老 Leader 变成 Follower,对新的 Leader 进行数据同步。即使这时老 Leader 对其余的 Follower 节点发送了请求,Follower 节点也会比较 ZXID 的值,由于高 32 位加 1 了, Follower 的 epoch(纪元)大于老 Leader 的 epoch(纪元),因此 Follower 会忽略这个请求。
这像改朝换代同样,前朝的剑不能斩本朝的官。
知道了这些名词,和上文提到的零散的知识点,其实崩溃恢复模式和消息广播模式的过程你们大体有所了解了。
先看看消息广播模式吧!
消息广播的模式的过程简图以下所示:
整个过程相似一个二阶段提交的过程,但却有所不一样,ZAB 协议简化了二阶段提交模型,在超过半数的 Follower 服务器已经反馈 ACK 以后就开始提交事务 Prososal 了,无需等待全部服务器响应。
结合上图,看看消息广播的具体细节:
在画一张详细点的流程图,更直观:
这就完成了整个消息广播了!
前文已经反复提过崩溃恢复模式了,其实就是从新选举出新的 Leader 服务器,选举完成后 Follower 服务器在再去同步 Leader 的数据。
运行中的服务再次进行从新选举,必定是出现某种异常,咱们知道在出现异常状况以前 Leader 的消息广播可能会处在任何一个阶段,有可能客户端的请求只是在 Leader 服务器上提出并未被提交,也可能请求已经被 Leader 服务器提交。
ZAB 协议对于不一样阶段的出现的数据不一致的状况作了兼容,保证:
针对以上的两个要求,在进行 Leader 选举时,之须要选举出集群中 ZXID 最大的事务 Proposal 便可,这样就能够省去 Leader 服务器检查 Proposal 的提交和丢弃工做了。由于 Leader 服务器的事务是最大的,一切以 Leader 服务器的数据为标准便可。
ZXID 在集群中其实并非惟一的,因此也有可能出现多 Follower 服务器 ZXID 相同的状况,这时候就须要比较 Zookeeper 的 SID 值。什么是 SID?SID 是一个数字,和 zookeeper 的 myid 一致,myid 就不要解释了,安装过 Zookeeper 的都知道,每台服务器都须要配置一个这样的文件,里面只有一个数字,用来标识这台服务器。由于每台机器的 myid 配置都不同,因此集群选举的时不会出现相等的状况。
选举时,比较大小的源码以下:
前面已经说过,出现选举 Leader 可能会出现两种状况:
但不管是启动期仍是运行期进行 Leader 选举,其选举过程都差不太多,我简单画个流程图:
结合上图,奔溃恢复模式下 Leader 选举的过程细节以下:
发起投票时有两种状况:
这就是崩溃恢复模式下选举 Leader 的过程了!
下面再简单介绍下数据同步的四种策略,这四种同步策略保证了Zookeeper 集群中的数据一致性,也解决了前文提出的两个问题,兼容了各类数据不一致的场景。
在数据同步以前,Leader 服务器会进行数据同步的初始化,首先会从 Zookeeper 的内存数据库中提取出事务前期对应的提议缓存队列,同时会初始化三个 ZXID 的值:
根据这三个参数,就能够肯定四种同步方式,分别为:
直接差别化同步
先回滚在差别化同步
仅回滚同步
全量同步
这就是四种同步策略,这几种同步方式也解决了上文提出的问题:
这些就是整个 ZAB 协议中崩溃恢复的内容。
ZAB协议看起来和Paxos有着相同之处,但它并非Paxos的典型实现,其实仍是有一些区别,ZAB协议中额外添加了一个同步的阶段,二者设计目标也不太同样,ZAB协议主要用于构建一个高可用的分布式数据主备系统,而Paxos算法则是用于构建一个分布式一致性的状态机。
Zookeeper 做为出色的分布式协调服务,目前读 QPS 达到 12w,出色的性能也让开发者更加青睐,其 ZAB 协议的核心分为两个部分:崩溃恢复、消息广播。
典型的应用场景有:
除此以外在大数据领域也有应用,例如:
在阿里巴巴集团内部实践的 Zookeeper 的产品也有不少,如:
咱们都知道 Zookeeper 是基于 ZAB 协议实现的,在介绍 ZAB 协议以前,先回顾一下 Zookeeper 的起源与发展。
Zookeeper 到底是在什么样的时代背景下被提出?为了解决了哪些棘手的问题?
Zookeeper 最先起源于雅虎研究院的一个研究小组。当时,研究人员发现,在雅虎的不少大型系统基本都须要依赖一个相似的系统来进行分布式协调,可是这些系统都存在分布式单点问题,因此雅虎的开发人员就试图开发出一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。
因而,Zookeeper 就诞生了!
Zookeeper 的出现不只解决了分布式系统下数据一致性的问题,并且经历过线上验证,不管是从性能、易用性、稳定性上来讲,都是工业级产品的标准。能够说在分布式系统中具备不可替代的核心地位,Hadoop、HBase、Storm 和 Solr 等大型分布式系统都已经将 Zookeeper 做为其核心组件,用于分布式协调。即使 Zookeeper 如此优秀,可是 Zookeeper 依然是免费且开源的,全世界成千上万的开发者都关注着它,陪同着一块儿成长和发展。
做为一个开发者不管是为了应付面试、晋升仍是我的技术成长的须要,都须要对 Zookeeper 有所了解,而学习 Zookeeper 的关键就是理解其核心部分:
ZAB 协议, 全称(Zookeeper Atomic Broadcast)Zookeeper 原子消息广播协议。
它与 Paxos 相似,也是一种数据一致性的算法。
在 ZAB 协议的开发设计人员在协议设计之初并无要求 ZAB 具备很好的扩展性,最初只是为了雅虎公司内部哪些高吞吐量、低延迟、健壮、简单的分布式系统场景设计的。基于 ZAB 协议,Zookeeper 实现了一种主备模式的系统架构来保持集群中各副本之间数据的一致性,简单架构图以下:
Zookeeper 用一个单一的主进程来接收并处理客户端的全部事物请求,并采用 ZAB 的原子广播协议将服务器数据状态以事物 Proposal 的形式广播到全部的副本进程中去。这样的模式就保证了,在同一时刻只有一个主进程来广播服务器的状态更变,所以可以很好地处理客户端大量的并发请求,这在 ZAB 协议中叫:消息广播。
除此以外,在分布式环境中事物的执行顺序也会存在必定的前后关系,好比:事务 C 的写入须要依赖事务 B 的写入,而事务 B 写入须要依赖事务 A 写入。这种先后依赖的顺序也对 ZAB 协议提出了一个要求:ZAB 协议须要保证若是一个状态的变动被处理了,那么全部其依赖的状态变动都已经被提早处理了。也就是须要顺序执行。
另外除了能正常广播消息、消息的顺序执行,主进程也可能随时会由于断电、机器宕机等异常状况没法提供服务,所以,ZAB 协议还须要作到在当前主进程出现上述异常状况的时候依然可以正常工做,这在 ZAB 协议中叫:崩溃恢复。
因此整个 ZAB 协议须要具有的核心特性已经被描述出来了,处理事务的请求的方式能够简单理解为:
全部的事务请求必须由一个全局惟一的服务器来协调处理,这样的服务器叫:Leader 服务器。其余的服务器被称为 Follower 服务器。Leader 服务器将客户端事务请求转化成一个事务 Prososal(提议),并将改 Proposal 分发给集群中全部的 Follower 服务器。以后 Leader 服务器接收了正确的反馈后,那么 Leader 就会再次向全部的 Follower 服务器分发 Commit 消息,要求将前一个 Proposal 提交。
这就简单阐述了 ZAB 协议中消息广播模式的部份内容。
ZAB 协议的包括两种模式:崩溃恢复、消息广播。
既然有两种模式,那 Zookeeper 集群何时进入奔溃恢复模式?何时进入消息广播模式呢?
在进入奔溃恢复模式时 Zookeeper 集群会进行 Leader 选举,通常有两种状况会发生选举:
选举出 Leader 服务器后,会进入消息广播模式,开始接收处理客户端的请求,前文已经描述,这里再也不赘述。
在深刻讲解 ZAB 协议的两个模式以前,先解释 Zookeeper 的几个相关概念,方便理解 ZAB 协议:
在前面提到 Zookeeper 的集群中的服务器有 Leader 和 Follower ,但实际在 ZAB 协议中 Zookeeper 有三种角色,分别是 Leader、Folower、Observer,它们的分工各有不一样:
Leader :负责整个Zookeeper 集群工做机制中的核心,主要工做有一下两个:
Follower :它是 Leader 的追随者,其主要工做有三个:
在知道了 Zookeeper 中有三种角色后,不经提问: Zookeeper 是如何知道本身目前是什么角色的呢?
在 ZAB 协议中定义:经过自身的状态来区分本身的角色的,在运行期间各个进程可能出现如下三种状态之一:
在组成 ZAB 协议的全部进程启动的时候,初始化状态都是 LOOKING 状态,此时进程组中不存在 Leader,选举以后才有,在进行选举成功后,就进入消息广播模式,此时 Zookeeper 集群中的角色状态就再也不是 LOOKING 状态。
前文咱们知道 zookeeper 消息有严格的因果关系,所以必须将每个事务请求按照前后顺序来进行排序与处理。那 Zookeeper 是如何保持请求处理的顺序的呢?其中很是关键的点就是 ZXID。
那 ZXID 到底是怎么发挥做用的呢?
Leader 服务器在接收到事务请求后,会为每一个事务请求生成对应的 Proposal 来进行广播,而且在广播事务 Proposal 以前,Leader 服务器会首先为这个事务 Proposal 分配一个全局单调递增的惟一 ID ,咱们称之为事务 ID(即 ZXID)。
ZXID 的设计也颇有特色,是一个全局有序的 64 位的数字,能够分为两个部分:
这里低 32 位 counter(计数器)单调递增还好理解,高 32 位 epoch(纪元)每次选举加 1 也许有些同窗就有疑问了,为何 epoch(纪元)每次选须要举加 1 ,它在整个 ZAB 协议中有什么做用?
咱们知道每当选举产生一个新的 Leader 服务器时生成一个新的 epoch(纪元)值,而在前文咱们知道,服务运行过程当中触发选举 Leader 的条件是:Leader 服务器的出现网络中断、奔溃退出、重启等异常状况,或者当集群中半数的服务器与该 Leader 服务器没法通讯时。
这说明整个 Zookeeper 集群此时处于一个异常的状况下,而在发生异常前,消息广播进行到哪一步骤咱们根本不知道,集群中的其余 Follower 节点从这种崩溃恢复状态从新选举出 Leader 后,若是老 Leader 又恢复了链接进入集群。此时老 Leader 的 epoch 确定会小于新 Leader 的 epoch,这时就将老 Leader 变成 Follower,对新的 Leader 进行数据同步。即使这时老 Leader 对其余的 Follower 节点发送了请求,Follower 节点也会比较 ZXID 的值,由于高 32 位加 1 了, Follower 的 epoch(纪元)大于老 Leader 的 epoch(纪元),因此 Follower 会忽略这个请求。
这像改朝换代同样,前朝的剑不能斩本朝的官。
知道了这些名词,和上文提到的零散的知识点,其实崩溃恢复模式和消息广播模式的过程你们大体有所了解了。
先看看消息广播模式吧!
消息广播的模式的过程简图以下所示:
<img src="https://upload-images.jianshu.io/upload_images/2710833-927c4264c545c4e7.png" alt="image.png" />
整个过程相似一个二阶段提交的过程,但却有所不一样,ZAB 协议简化了二阶段提交模型,在超过半数的 Follower 服务器已经反馈 ACK 以后就开始提交事务 Prososal 了,无需等待全部服务器响应。
结合上图,看看消息广播的具体细节:
在画一张详细点的流程图,更直观:
<img src="https://upload-images.jianshu.io/upload_images/2710833-e53b8b881792203a.png" alt="image.png" />
这就完成了整个消息广播了!
前文已经反复提过崩溃恢复模式了,其实就是从新选举出新的 Leader 服务器,选举完成后 Follower 服务器在再去同步 Leader 的数据。
运行中的服务再次进行从新选举,必定是出现某种异常,咱们知道在出现异常状况以前 Leader 的消息广播可能会处在任何一个阶段,有可能客户端的请求只是在 Leader 服务器上提出并未被提交,也可能请求已经被 Leader 服务器提交。
ZAB 协议对于不一样阶段的出现的数据不一致的状况作了兼容,保证:
针对以上的两个要求,在进行 Leader 选举时,之须要选举出集群中 ZXID 最大的事务 Proposal 便可,这样就能够省去 Leader 服务器检查 Proposal 的提交和丢弃工做了。由于 Leader 服务器的事务是最大的,一切以 Leader 服务器的数据为标准便可。
ZXID 在集群中其实并非惟一的,因此也有可能出现多 Follower 服务器 ZXID 相同的状况,这时候就须要比较 Zookeeper 的 SID 值。什么是 SID?SID 是一个数字,和 zookeeper 的 myid 一致,myid 就不要解释了,安装过 Zookeeper 的都知道,每台服务器都须要配置一个这样的文件,里面只有一个数字,用来标识这台服务器。由于每台机器的 myid 配置都不同,因此集群选举的时不会出现相等的状况。
选举时,比较大小的源码以下:
<img src="https://upload-images.jianshu.io/upload_images/2710833-bbcba5240c2a1db0.png" alt="image.png" />
前面已经说过,出现选举 Leader 可能会出现两种状况:
但不管是启动期仍是运行期进行 Leader 选举,其选举过程都差不太多,我简单画个流程图:
<img src="https://upload-images.jianshu.io/upload_images/2710833-d87f4a39511a8630.png" alt="image.png" />
结合上图,奔溃恢复模式下 Leader 选举的过程细节以下:
发起投票时有两种状况:
这就是崩溃恢复模式下选举 Leader 的过程了!
下面再简单介绍下数据同步的四种策略,这四种同步策略保证了Zookeeper 集群中的数据一致性,也解决了前文提出的两个问题,兼容了各类数据不一致的场景。
在数据同步以前,Leader 服务器会进行数据同步的初始化,首先会从 Zookeeper 的内存数据库中提取出事务前期对应的提议缓存队列,同时会初始化三个 ZXID 的值:
根据这三个参数,就能够肯定四种同步方式,分别为:
直接差别化同步
先回滚在差别化同步
仅回滚同步
全量同步
这就是四种同步策略,这几种同步方式也解决了上文提出的问题:
这些就是整个 ZAB 协议中崩溃恢复的内容。
ZAB协议看起来和Paxos有着相同之处,但它并非Paxos的典型实现,其实仍是有一些区别,ZAB协议中额外添加了一个同步的阶段,二者设计目标也不太同样,ZAB协议主要用于构建一个高可用的分布式数据主备系统,而Paxos算法则是用于构建一个分布式一致性的状态机。
Zookeeper 做为出色的分布式协调服务,目前读 QPS 达到 12w,出色的性能也让开发者更加青睐,其 ZAB 协议的核心分为两个部分:崩溃恢复、消息广播。
典型的应用场景有:
除此以外在大数据领域也有应用,例如:
在阿里巴巴集团内部实践的 Zookeeper 的产品也有不少,如:
欢迎关注个人我的微信公众号:java之旅