zookeeper 之调研总结

1、ZooKeeper是什么?

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby的一个开源的实现,是集群的管理者,监视着集群各个节点的状态,根据节点提交的反馈进行下一步合理操作。最终将简单易用的接口和新能高效、功能稳定的系统提供给用户。

2、ZooKeeper提供了什么?

1)文件系统

2)通知机制

Zookeeper文件系统

每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

有四种类型的znode: 

1)PERSISTENT-持久化目录节点 

客户端与zookeeper断开连接后,该节点依旧存在 

2)PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点 

客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 

3)EPHEMERAL-临时目录节点 

客户端与zookeeper断开连接后,该节点被删除 

4)EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点 

客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号 

4264270fdaa76f5688c2f311d83878760db.jpg

Zookeeper通知机制


客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

3、Zookeeper做了什么?


1)命名服务 

2)配置管理   

3)集群管理   

4)分布式锁  

5)队列管理

6)负载均衡


Zookeeper命名服务



在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。

Zookeeper的命名服务有两个应用方向,一个是提供类似JNDI的功能,利用zookeepeer的树型分层结构,可以把系统中各种服务的名称、地址以及目录信息存放在zookeeper,需要的时候去zookeeper中读取。

另一个,是利用zookeeper顺序节点的特性,制作分布式的ID生成器,写过数据库应用的朋友都知道,我们在往数据库表中插入记录时,通常需要为该记录创建唯一的ID,在单机环境中我们可以利用数据库的主键自增功能。但在分布式环境则无法使用,有一种方式可以使用UUID,但是它的缺陷是没有规律,很难理解。利用zookeeper顺序节点的特性,我们可以生成有顺序的,容易理解的,同时支持分布式环境的序列号。

原理是,生成节点时,会生成唯一的节点名称,可以拿来作为唯一id(具有目录结构,名称具有意义,用来命名是不错的选择)。


Zookeeper配置管理


程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好

5f9dfd5e23a90553b3df78cd924235dd7d3.jpg

cdb521f63f752a4ca8625dc23e8bf981bce.jpg

fd7d6e83bcd95777ebdb736ccfdf2c9f662.jpg

zookeeper提供了节点watch的功能,zookeeper的client(对外提供服务的server)监控zookeeper上的节点(znode),当节点变动的时候,client会收到变动事件和变动后的内容,基于zookeeper的这个特性,我们可以给服务器集群中的所有机器(client)都注册watch事件,监控特定znode,节点中存储部署代码的配置信息,需要更新代码的时候,修改znode中的值,服务器集群中的每一台server都会收到代码更新事件,然后触发调用,更新目标代码。也可以很容易的横向扩展,可以随意的增删机器,机器启动的时候注册监控节点事件即可。

Zookeeper集群管理


所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 

对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。

新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。

 

6334f1ad6755546eb8e125815b931e52fc3.jpg

Zookeeper分布式锁


有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。 
对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。 
对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便

 

549df008455e4c6156d8c8e8aa8992b5bd5.jpg

从一个根节点创建节点时候,有顺序号,根据顺序号,最小顺序号先获得锁,如果不是最小,则获得比当前序号小的前一个序号的节点,并且在这个节点上注册通知,这个节点删除后,客户端获得通知,得到通知后再次判断自己是否是最小的,如果是则获取锁,否则持续以上流程。(释放锁后,将当前节点删除)。

代码实现,请再码云下载,地址如下:

https://gitee.com/hddlxx/zookeeper_lock.git

Zookeeper负载均衡

zookeeper实现负载均衡其实原理很简单,zookeeper 的数据存储类似于liunx的目录结构。首先建立servers节点,并建立监听器监视servers子节点的状态(用于在服务器增添时及时同步当前集群中服务器列表)。在每个服务器启动时,在servers节点下建立子节点worker server(可以用服务器地址命名),并在对应的字节点下存入服务器的相关信息。这样,我们在zookeeper服务器上可以获取当前集群中的服务器列表及相关信息,可以自定义一个负载均衡算法,在每个请求过来时从zookeeper服务器中获取当前集群服务器列表,根据算法选出其中一个服务器来处理请求。

a42bcf25de8c30b1f1939b1d3b9b2e31801.jpg

 4、分布式与数据复制 


Zookeeper作为一个集群提供一致的数据服务,自然,它要在所有机器间做数据复制。数据复制的好处: 

1)容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作; 

2)提高系统的扩展能力 :把负载分布到多个节点上,或者增加节点来提高系统的负载能力; 

3)提高性能:让客户端本地访问就近的节点,提高用户访问速度。 

从客户端读写访问的透明度来看,数据复制集群系统分下面两种: 

1)写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,可以读取任何一个节点。这种情况下客户端需要对读与写进行区别,俗称读写分离; 

2)写任意(Write Any):对数据的修改可提交给任意的节点,跟读一样。这种情况下,客户端对集群节点的角色与变化透明。

对zookeeper来说,它采用的方式是写任意。通过增加机器,它的读吞吐能力和响应能力扩展性非常好,而写,随着机器的增多吞吐能力肯定下降(这也是它建立observer的原因),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,还是立即复制快速响应。

4f25c54337a71b76f0540a3187d9fc87197.jpg

0735ecef3d5bace9bcb8cb4cabb236a121a.jpg

5、Zookeeper设计目的


1)最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。 
2)可靠性:具有简单、健壮、良好的性能,如果消息被到一台服务器接受,那么它将被所有的服务器接受。 
3)实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。 
4)等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。 
5)原子性:更新只能成功或者失败,没有中间状态。 
6.顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。 

6、Zookeeper工作原理


Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。 
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。



7、Zookeeper 下 Server工作状态


每个Server在工作过程中有三种状态: 
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步

3a59bc6af1b21469841f8a3dbbea3052a09.jpg

703b0022f6cb8497b339bf57e3946773e85.jpg

8、Zookeeper选主流程(basic paxos)


当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。
1)选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server; 
2)选举线程首先向所有Server发起一次询问(包括自己); 
3)选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中; 
4)收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server; 
5)线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。 通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1. 每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图所示: 

 

 

 9、Zookeeper选主流程(fast paxos)


fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。

10、Zookeeper同步流程



选完Leader以后,zk就进入状态同步过程。 

1)Leader等待server连接; 

2 )Follower连接leader,将最大的zxid发送给leader; 

3 )Leader根据follower的zxid确定同步点; 

4 )完成同步后通知follower 已经成为uptodate状态; 

5 )Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

11、Zookeeper工作流程-Leader



1 )恢复数据; 

2 )维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型; 

3 )Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。 

         PING 消息是指Learner的心跳信息;

         REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;

         ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;

         REVALIDATE消息是用来延长SESSION有效时间。

12、Zookeeper工作流程-Follower



Follower主要有四个功能: 



1)向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息); 
2)接收Leader消息并进行处理; 
3)接收Client的请求,如果为写请求,发送给Leader进行投票;
4)返回Client结果。 
 


Follower的消息循环处理如下几种来自Leader的消息: 



1 )PING消息: 心跳消息; 

2 )PROPOSAL消息:Leader发起的提案,要求Follower投票; 

3 )COMMIT消息:服务器端最新一次提案的信息; 

4 )UPTODATE消息:表明同步完成; 

5 )REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息; 

6 )SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。

13、Zookeeper分布式示例

e007e5d6aa76375349165f4aa31605c0519.jpg

14、Zookeeper节点数据操作流程

 

 

1)在Client向Follwer发出一个写的请求

2)Follwer把请求发送给Leader

3)Leader接收到以后开始发起投票并通知Follwer进行投票

4)Follwer把投票结果发送给Leader

5)Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;

6)Follwer把请求结果返回给Client

 

15、Zookeeper中的zxid

znode节点的状态信息中包含czxid, 那么什么是zxid呢?


ZooKeeper状态的每一次改变, 都对应着一个递增的Transaction id, 该id称为zxid. 由于zxid的递增性质, 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2发生.

创建任意节点, 或者更新任意节点的数据, 或者删除任意节点, 都会导致Zookeeper状态发生改变, 从而导致zxid的值增加.

16、Zookeeper中的ZAB协议

a430616eaec034af6c2e1eefa196cc7438c.jpg

ZAB的协议核心是在整个zookeeper集群中只有一个节点即Leader将客户端的写操作转化为事物(或提议proposal)。Leader节点再数据写完之后,将向所有的follower节点发送数据广播请求(或数据复制),等待所有的follower节点反馈。在ZAB协议中,只要超过半数follower节点反馈OK,Leader节点就会向所有的follower服务器发送commit消息。即将leader节点上的数据同步到follower节点之上。

971e86d4073f64e9109cadb132ad9695265.jpg

ffa6c74066b7f238602f03836e3b68575d8.jpg

ZAB协议是专门为zookeeper实现分布式协调功能而设计。zookeeper主要是根据ZAB协议是实现分布式系统数据一致性。

ZAB协议要求每个leader都要经历三个阶段,即发现,同步,广播。

1)发现:即要求zookeeper集群必须选择出一个leader进程,同时leader会维护一个follower可用列表。将来客户端可以这follower中的节点进行通信。

2)同步:leader要负责将本身的数据与follower完成同步,做到多副本存储。这样也是体现了CAP中高可用和分区容错。follower将队列中未处理完的请求消费完成后,写入本地事物日志中。

3)广播:leader可以接受客户端新的proposal请求,将新的proposal请求广播给所有的follower。Zookeeper设计目标

Zab协议有两种模式,它们分别是恢复模式(选主)和广播 模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后, 恢复模式就结束了。
状态同步保证了leader和Server具有相同的系统状态。为了保证事务的顺序一致性,zookeeper采用了递增的事务id号 (zxid)来标识事务。

17、Zookeeper总结

zookeeper作为当今最流行的分布式系统应用协调框架,采用zab协议的最大目标就是建立一个高可用可扩展的分布式数据主备系统。即在任何时刻只要leader发生宕机,都能保证分布式系统数据的可靠性和最终一致性。

深刻理解ZAB协议,才能更好的理解zookeeper对于分布式系统建设的重要性。以及为什么采用zookeeper就能保证分布式系统中数据最终一致性,服务的高可用性。

18、特别强调

如果想了解分布式锁的实现过程,请在码云下载,下载地址如下:

https://gitee.com/hddlxx/zookeeper_lock.git

 

转载于:https://my.oschina.net/u/2269430/blog/2870457

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值