1、zookeeper与zab协议
- zookeeper为分布式应用提供了高效且可靠的分布式协调服务,提供了如统一命名服务、配置管理和分布式锁等分布式的基础服务。在分布式数据的一致性方面,zk并没有直接采用paxos算法,而是采用zab的一致性协议。
一、初识zk
1、概述
- ZooKeeper是一个开源的分布式协调服务。ZooKeeper框架最初是在“Yahoo!"上构建的,用于以简单而稳健的方式访问他们的应用程序。 后来,Apache ZooKeeper成为Hadoop,HBase和其他分布式框架使用的有组织服务的标准。 例如,Apache HBase使用ZooKeeper跟踪分布式数据的状态。ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
原语:操作系统或计算机网络用语范畴。是由若干条指令组成的,用于完成一定功能的一个过程。具有不可分割性·即原语的执行必须是连续的,在执行过程中不允许被中断。
- zk是一个典型的分布式数据一致性的解决方案。分布式应用可以基于它实现数据的发布订阅、负载均衡、命名服务、分布式协调和通知、集群管理、分布式锁等。zk可以保证分布式的一致性特性。
-
Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。
zookeeper作为dubbo注册中心
2、特点
顺序一致性:从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
原子性:更新只能成功或者失败,没有中间状态。
单一视图(无论客户端连接的哪一个zk服务器,其看到的服务端数据模型是一样的)
可靠性:一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。
实时性(一定时间内保证可以读取到最新值)
3、zk设计目标
- zk致力于提供一个高性能、高可用、且具有严格的顺序访问控制能力(主要是写操作的严格顺序性)的分布式协调服务。
(1)目标一:简单的数据模型
zk存储结构zk使得分布式程序能够通过一个共享的、树形结构的命名空间进行相互协调。(这里的树形结构,指zk服务器内存中的一个数据模型,由一些列被称为ZNode的数据节点组成)。zk将全量数据存储在内存中,以此来提高服务器吞吐、减少延时的目的。
(2)可以构建集群
zk架构图一个zk服务器集群通常由一组机器组成,一般3-5台机器就可以组成一个可用的zk集群了。组成zk集群的每台机器都会在内存中维护当前的服务器状态,并且每台机器都互相保持着通信。只要集群中存在超过一般的机器能够正常工作,那么整个集群就能正常保持服务。
- 上图中每一个Server代表一个安装Zookeeper服务的服务器。组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 Zab 协议(Zookeeper Atomic Broadcast)来保持数据的一致性。
(3)顺序访问
来自客户端的每一个版本请求,zk都会分配一个全局唯一的递增编号,这个编号表示了所有事物操作的先后顺序
(4)高性能
zk将全量数据存储在内存中,并直接服务于客户端的所有非事物请求,适用于读操作为主的应用场景。根据有关资料显示压测可达到12-13W的qps。
4、zk基本概念
(1)集群模式:zk引入leader、follower和observer三个角色。通过选举产生leader机器,leader服务器为客户端提供读和写服务;follower和observer都能提供读服务,但是observer不参与选举。
(2)会话session:在zk中,一个客户端连接是指客户端和服务端的一个TCP长连接。对外默认端口是2181,客户端启动的时候,首先会和服务端建立一个TCP连接,从第一次建立开始,客户端会话的生命周期也就开始了,通过这个连接,客户端能够通过心跳检测与服务端保持有效的会话,也能够向zk服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的watch事件通知;session的sessionTimeout用来设置一个客户端会话的超时时间,由于为止原因,导致客户端连接断开,只要sessionTimeout规定的时间内能够重新连上集群中任意一台服务器,那么之前创建的会话仍然有效。
(3)数据节点ZNode:zk中数据节点指数据模型中的数据单元ZNode。数据模型是一颗树,保存在内存中,由\进行分割的路径,就是一个ZNode;在每一个ZNode上都会保存自己的数据内容,同时会保存一些列的属性信息。
1、持久性节点:指一旦这个ZNode被创建,除非主动进行ZNode移除操作,否则这个ZNode将一直保存在zk中
2、临时节点:生命周期和客户端会话绑定,一旦客户端会话失效,这个客户端创建的所有临时节点都会被移除。
(4)版本:对应于每一个ZNode,zk会为其维护一个叫做stat的数据结构,stat中记录了这个ZNode的三个数据版本,分别是version(当前ZNode版本)、cversion(当前ZNode子节点版本)和aversion(当前ZNode的ACL版本)
(5)Watcher:watche(事件监听器)是zk一个重要的特性,zk允许用户在指定的节点上注册一些东watcher,并且在一些特定的事件触发的时候,zk服务端会将事件通知感兴趣的客户端上去,该机制是zk实现分布式协调的重要特性。
(6)ACL:zk采用ACL来进行权限控制,zk定义了五种权限(create创建子节点、read获取节点数据和子节点列表、write更新节点数据、delete删除子节点、admin设置节点ACL)
5、小结
(1)ZooKeeper是一个开源的分布式协调服务,提供了分布式数据一致性的解决方案。
(2)ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务),构建zk集群时候节点个数必须大于1且是奇数。
(3)ZooKeeper 将数据保存在内存中,这也就保证了 高吞吐量和低延迟(但是内存限制了能够存储的容量不太大,此限制也是保持znode中存储的数据量较小的进一步原因)。
(4)ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)
(5)ZooKeeper有临时节点的概念。
(6)ZooKeeper 底层其实只提供了两个功能:①管理(存储、读取)用户程序提交的数据;②为用户程序提交数据节点监听服务。
二、ZAB协议
1、ZAB协议与paxos协议关系
- Paxos 算法应该可以说是 ZooKeeper 的灵魂了。但是,ZooKeeper 并没有完全采用 Paxos算法 ,而是使用 ZAB 协议作为其保证数据一致性的核心算法。另外,在ZooKeeper的官方文档中也指出,ZAB协议并不像 Paxos 算法那样,是一种通用的分布式一致性算法,它是一种特别为Zookeeper设计的崩溃可恢复的原子消息广播算法。
- ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。
ZAB协议的开发设计人员在协议设计之初并没有要求其具有很好的扩展性,最初只是雅虎公司内部哪些高吞吐、低延迟、健壮、简单的分布式系统场景设计的,因此ZAB协议并不想paxos协议那样,是一种通用的分布式一致性算法,是一种特别为zk设计的奔溃可恢复的原子消息广播算法。
2、ZAB协议的核心
- zk的核心是定义了那些请求会改变zk服务器数据状态的事物请求的处理方式。(其实核心就是原子广播)
所有事物的请求必须由一个全局的唯一的服务器来协调处理,这样的服务器称为leader服务器,余下的服务器称为follow服务器。leader服务器负责将一个客户端请求转换为一个(事物)proposal提议,并将该提议分发到集群中所有的follow服务器。之后leader服务器等待follow服务器的反馈,一旦超过半数的follow服务器进行了正确的反馈后,leader服务器将再次向所有的follow服务器分发commit请求,要求将前一个proposal进行提交。
3、ZAB协议基本模式(崩溃恢复和消息广播)
(1)崩溃恢复:当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进人恢复模式并选举产生新的Leader服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该Leader服务器完成了状态同步之后,ZAB协议就会退出恢复模式。其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致。
(2)消息广播:当集群中已经有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个服务框架就可以进人消息广播模式了。 当一台同样遵守ZAB协议的服务器启动后加人到集群中时,如果此时集群中已经存在一个Leader服务器在负责进行消息广播,那么新加人的服务器就会自觉地进人数据恢复模式:找到Leader所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。正如上文介绍中所说的,ZooKeeper设计成只允许唯一的一个Leader服务器来进行事务请求的处理。Leader服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议;而如果集群中的其他机器接收到客户端的事务请求,那么这些非Leader服务器会首先将这个事务请求转发给Leader服务器。
三、zk原理探究
1、zk角色概念
zk集群结构图- 领导者(leader),负责进行投票的发起和决议,更新系统状态
- 学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票。
- Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
-
客户端(client),请求发起方
zk各个角色总结归纳 - zk集群的服务节点在工作过程中有三种状态。LOOKING:当前Server不知道leader是谁,正在搜寻;LEADING:当前Server即为选举出来的leader;FOLLOWING:leader已经选举出来,当前Server与之同步
2、zk的读写机制
- 首先zk是由多个server构成的集群,集群中只有一个leader,多个leaner(多个follow和observer),leader负责总协调(比如实施更新请求转发),每一个leaner保存一份数据的副本。zk通过zab协议的原子广播模式实现了数据的全局一致性。
3、zk节点数据操作流程
zk数据节点操作流程1.在Client向Follwer发出一个写的请求
2.Follwer把请求发送给Leader
3.Leader接收到以后开始发起投票并通知Follwer进行投票
4.Follwer把投票结果发送给Leader
5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给follow,然后commit;
6.Follwer把请求结果返回给Client
4、zk选举
- 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。
(1)集群启动时候选举
以一个简单的例子来说明整个选举的过程:假设有五台服务器组成的 zookeeper 集群,它们 的 serverid 从 1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点 上,都是一样的。假设这些服务器依序启动,来看看会发生什么
1、服务器 1 启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的 选举状态一直是 LOOKING 状态
2、服务器 2 启动,它与最开始启动的服务器 1 进行通信,互相交换自己的选举结果,由于 两者都没有历史数据,所以 id 值较大的服务器 2 胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是 3),所以服务器 1、2 还是继续保持 LOOKING 状态
3、服务器 3 启动,根据前面的理论分析,服务器 3 成为服务器 1,2,3 中的老大,而与上面不 同的是,此时有三台服务器(超过半数)选举了它,所以它成为了这次选举的 leader
4、服务器 4 启动,根据前面的分析,理论上服务器 4 应该是服务器 1,2,3,4 中最大的,但是 由于前面已经有半数以上的服务器选举了服务器 3,所以它只能接收当小弟的命了
5、服务器 5 启动,同 4 一样,当小弟
(2)奔溃恢复时候的选举。
- 随机让一个服务器从新开始选举,并配合version、serverid 和逻辑时钟等概念。
5、zid概念
- znode节点的状态信息中包含zxid,ZooKeeper状态的每一次改变, 都对应着一个递增的Transaction id, 该id称为zxid. 由于zxid的递增性质, 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2发生.创建任意节点, 或者更新任意节点的数据, 或者删除任意节点, 都会导致Zookeeper状态发生改变, 从而导致zxid的值增加.
6、zk状态同步流程
zk状态同步流程图- 选完Leader以后,zk就进入状态同步过程。
- Leader等待server连接;
2 .Follower连接leader,将最大的zxid发送给leader;
3 .Leader根据follower的zxid确定同步点;
4 .完成同步后通知follower 已经成为uptodate状态;
5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
7、zk中leader工作机制
zk中leader的工作流程1 .恢复数据;
2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;
3 .Learner的消息类型主要有PING消息(Learner的心跳信息)、REQUEST消息(Follower发送的提议信息,包括写请求及同步请求)、ACK消息( Follower的对提议的回复,超过半数的Follower通过,则commit该提议)、REVALIDATE消息(用来延长SESSION有效时间),根据不同的消息类型,进行不同的处理。
8、 follow的工作机制
follow工作机制1.向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
2.接收Leader消息并进行处理;
3.接收Client的请求,如果为写请求,发送给Leader进行投票;
4.返回Client结果。
9、Observer工作机制
- 为了支持更多的客户端,需要增加更多Server,Server增多,投票阶段延迟增大,影响性能.。权衡伸缩性和高吞吐率,引入Observer,Observer不参与投票(其他和follow职责一样)
- 加入更多Observer节点,提高伸缩性,同时不影响吞吐率
10、zk中保证事物的顺序性
- 为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
参考:
《从Paxos到Zookeeper 》
https://segmentfault.com/a/1190000016349824
https://blog.csdn.net/xqb_756148978/article/details/52259381
https://www.cnblogs.com/qingyunzong/p/8632995.html#_label4_4
https://blog.csdn.net/qq_22094297/article/details/80692624