大数据学习之Zookeeper

Zookeeper简介

Zookeeper是一个为分布式应用所设计的开源协调服务。它可以为用户提供同步、配置管理、分组和命名等服务。开发者意欲将Zookeeper设计成一个易于编程的环境,所以它的文件系统使用了我们所熟悉的目录树结构。Zookeeper是使用Java编写的,但是它支持Java和C两种编程语言。
总所周知,协调服务是非常容易出错的,而且很难从故障中恢复。Zookeeper的设计目的就是为了减轻分布式应用程序所承担的协调服务。

Zookeeper设计目标

1.简单化:
Zookeeper允许分布式的进程通过共享体系的命名空间来进行协调,这个命名空间的组织与标准的文件系统非常相似,它是由一些数据寄存器组成的。在Zookeeper中,这些寄存器被称为Znode。他们和文件目录非常相似,典型的文件系统的基于存储设备的,然而,Zookeeper的数据却是存放在内存当中的,这就意味着Zookeeper可以达到一个高的吞吐量,并且有低的延迟。Zookeeper的实现非常重视高性能、高可靠性,以及严格的有序访问。
Zookeeper性能上的特点决定了它能够用在大型的、分布式的系统当中。从可靠性方面来说,它并不会因为一个节点的错误而崩溃。除此之外,它严格的序列访问控制意味着复杂的控制原语可以应用在客户端上。

2.健壮性
组成Zookeeper服务的服务器必须互相知道其他服务器的存在。他们维护着一个处于内存中的状态镜像,以及一个位于存储器中的交换日志和快照。只要大部分的服务器可用,那么Zookeeper服务就可用。
如果客户端连接到单个Zookeeper服务器上,那么这个客户端就管理者一个TCP连接,并且通过这个TCP连接来发送请求、获得响应、获取监测事件,以及发送心跳。如果连接到服务器上的TCP连接断开,客户端将连接到其他的服务器上。

3.有序性
Zookeeper可以为每一次更新操作赋予一个版本号,并且此版本号是全局有序的,不存在重复的情况。Zookeeper所提供的很多服务也是基于此有序性的特点来完成的。

4.速度优势
它在读取主要负载时尤其快。Zookeeper应用程序在上千台机器的节点上运行。另外,需要注意的是Zookeeper有这样一个特点:当读工作比写工作更多的时候,它执行的性能会更好。

Zookeeper主要功能

1.命名服务:
这个可以简单理解为一个电话薄,电话号码不好记,但是人名好记,要打谁的电话,直接查人名就好了。 分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同服务; 类似于域名与ip之间对应关系,域名容易记住; 通过名称来获取资源或服务的地址,提供者等信息。

2.配置管理
把应用配置放置zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。
在这里插入图片描述
3.集群管理
节点(机器)增删及Master选取。
节点增删:所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它被删了。新机器加入 也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了。
Master选取:所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
在这里插入图片描述
4.分布式锁:
基于zookeeper一致性文件系统,实现锁服务。锁服务分为保存独占时序控制两类。
保存独占:将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除自己创建的distribute_lock 节点就释放锁。
时序控制:基于/distribute_lock锁,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。

5.队列管理
分布式队列分为两种:同步队列,FIFO队列(先进先出)。
同步队列:当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。
FIFO队列:和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。

6.分布式于数据复制:
Zookeeper作为一个集群提供一致的数据服务,必然在所有机器间做数据复制。数据复制好处:
(1)容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作。
(2)提高系统的扩展能力:把负载分布到多个节点上,或者增加节点来提高系统的负载能力;
(3)性能提升:让客户端本地访问就近节点,提高用户访问速度。

Zookeeper主要特点

1.最终一致性:为客户端展示同一视图,这是zookeeper最重要的功能。
2.可靠性:如果消息被到一台服务器接受,那么它将被所有的服务器接受。
3.实时性:Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4.等待无关(wait-free):慢的或者失效的client不干预快速的client的请求。
5.原子性:更新只能成功或者失败,没有中间状态。
6.顺序性:所有Server,同一消息发布顺序一致

Zookeeper数据模型

Zookeeper提供的命名空间与标准的文件系统非常相似。唯一不同的地方是命名空间中的每个节点可以有和它自身或它的子节点相关联的数据。这就好像是一个文件系统,只不过文件系统中的文件还可以具有目录的功能。另外,指向节点的路径必须使用规范的绝对路径来表示,并且以斜线“/”来分隔。需要注意的是,在Zookeeper中不允许使用相对路径。如下图所示:
在这里插入图片描述
在这里插入图片描述
1.Znode
Zookeeper目录树中的每一个节点对应着一个Znode。每个Znode维护着一个属性结构,它包含数据的版本号(data Version)、时间戳(ctime、mtime)等状态信息。Zookeeper正是使用节点的这些特性来实现它的某些特定功能。每当Znode的数据改变时,它的相应的版本号会增加。每当客户端检索数据是,它将同时检索数据的版本号。并且若一个客户端执行了某个节点的更新或删除操作,它也必须提供要被操作的数据的版本号。如果所提供的数据版本号于实际的不匹配,那么这个操作将会失败。

Znode是客户端要访问的Zookeeper的主要实体,它包含以下几个主要特征:
1)watches:
客户端可以在节点上设置watch(监视器)。当节点的状态发生改变时(数据的增、删、改等操作)将会触发watch对应的操作。当watch被触发时,Zookeeper将会向客户端发送且仅发送一个通知,因为watch只能被触发一次。
2)数据访问:
Zookeeper中的每个节点上存储的数据需要被原子性的操作。也就是说,读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。另外,每一个节点都拥有自己的ACL(访问控制列表),这个列表规定了用户的权限,即限定了特定用户对目标节点可以执行的操作。
3)临时节点
Zookeeper中的节点有两种,分别是:临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。Zookeeper临时节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,当然也可以手动删除。另外,需要注意的是,Zookeeper的临时节点不允许拥有孩子节点。相反,永久节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,它们才会被删除。
4)顺序节点(唯一保证性)
当创建Znode节点的时候,用户可以请求在Zookeeper的路劲结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为“%010d”(10位数字,没有数值的数据位用0填充)。

2.Zookeeper中的时间
Zookeeper中有多种记录时间的形式,其中包括如下几个主要属性:
1)Zxid
致使Zookeeper节点状态改变的每一个操作都将使节点接收到一个zxid格式的时间戳,并且这个时间戳是全局有序的。也就是说,每一个节点改变都将产生一个唯一的zxid。如果zxid1的值小于zxid2的值,那么zxid1所对应的时间发生在zxid2所对应的时间之前。实际上,Zookeeper的每个节点维护着三个zxid值,分别为:cZxidmZxid、和pZxid。cZxid是节点的创建时间与所对应的Zxid格式时间戳,mZxid是节点的修改时间所对应的Zxid格式时间戳。
2)版本号:
对节点的每一个操作都将致使这个节点的版本号增加。每个节点维护着三个版本号,他们分别为:dataVersion(节点数据版本号)、cversion(子节点版本号)、aclVersion(节点所拥有的ACL的版本号)。

Zookeeper ACL

Zookeeper使用ACL(访问控制列表)对Znode进行访问控制。ACL的实现和UNIX文件访问许可非常相似:它使用许可位来对一个节点的不同操作进行允许或禁止的权限控制。但是,和标准的UNIX许可不同的是,Zookeeper节点有user(文件拥有者)、group和world三种标准模式,并且没有节点所有者的概念。
需要注意的是,一个ACL和一个Zookeeper节点相对应。并且,父节点的ACL与孩子节点的ACL是相互独立的。也就是说,ACL不能被孩子节点所继承,父节点所拥有的权限与孩子节点所拥有的权限没有任何关系。

Zookeeper定义了以下5种ACL权限:
CREATE(创建):创建孩子节点;
READ(读):从节点获取数据或列出节点的所有孩子节点;
WRITE(写):设置节点的数据;
DELETE(删除):删除孩子节点;
ADMIN(管理员):可以设置权限。

Zookeeper的系统架构

在这里插入图片描述
系统模型如上图上所示。
1.Zookeeper的角色:
领导者(leader):负责进行投票的发起和决议,更新系统状态。
学习者(learner):包括跟随者(follower)和观察者(observer)。

follower:用于接收客户端请求并向客户端返回结果,在选主过程中参与投票。
observer:可以接收客户端连接,将写请求转发给leader,但observer不参加投票过程,
只同步leader的状态,observer的目的是为了扩展系统,提高读取速度。

客户端(client):请求发起方。

在这里插入图片描述
2.核心
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识 leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

3.状态:
1)LOOKING:当前Server不知道leader是谁,正在搜寻。
2)LEADING:当前Server即为选举出来的leader。
3)FOLLOWING:leader已经选举出来,当前Server与之同步。
在这里插入图片描述
在这里插入图片描述
4.选主流程
当leader崩溃或者leader失去大多数的follower,这时候Zookeeper进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic 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会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:
在这里插入图片描述
fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:
在这里插入图片描述
5.同步流程:
选举完leader以后,Zookeeper就进入状态同步过程:
1) leader等待server连接;

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

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

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

5)Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
流程图如下所示:
在这里插入图片描述
6.Leader工作流程:
Leader主要有三个功能:
1)恢复数据;
2)维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;
3)Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。

PING消息是指Learner的心跳信息;
REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;
ACK消息是Follower的对提议的回复,超过半数的Follower通过,则commit该提议;
REVALIDATE消息是用来延长SESSION有效时间。

Leader的工作流程简图如下:
在这里插入图片描述
7.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结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
Follower的工作流程简图如下所示:

在这里插入图片描述
8.Zookeeper监视(Watches)
Zookeeper可以为所有的读操作设置watch(事件监听),这些读操作包括:exists(),getChildren()及getData()。watch事件是一次性的触发器,当watch的对象状态发生改变时,将会触发此对象上watch所对应的事件。

在使用watch时需要注意,watch是一次性触发器,并且只有在数据发生改变时,watch事件才会被发送给客户端。例如:如果一个客户端进行了getData("/znode1",true)操作,并且之后"/znode1"的数据被改变或者删除了,那么客户端将获得一个关于"znode1"的事件。如果“znode1”再次改变,那么将不再有watch事件发送给客户端,除非客户端为另一个读操作重新设置了一个watch。

watch事件将被异步的发送给客户端,并且Zookeeper为watch机制提供了有序的一致性保证。理论上,客户端接收watch事件的时间要快于其看到watch对象状态改变的时间。

Zookeeper所管理的watch可以分为两类:一类是数据watch(data watches),另一类是孩子watch(child watches)。getData()和exists()负责设置数据watch,getChildren()负责设置孩子watch。我们可以通过操作返回的数据来设置不同的watch。getData()和exists()返回关于节点数据的信息,getChildren()返回孩子列表。因此,setData()将触发设置了数据watch的对应事件。一个成功的create() 操作将触发Znode的数据watch,以及孩子watch。一个成功的delete()操作将触发数据watch和孩子watch,因为Znode被删除的瘦,它的child watch也将被删除。

Watch由客户端所连接的Zookeeper服务器及本地维护,因此watch可以非常容易地设置、管理和分派。当客户端连接到新的服务器时,任何的会话事件都将可能触发watch。另外,当从服务器断开连接的时候,watch将不会被拒收。但是,当一个客户端重新建立连接的时候,任何先前注册过的watch都会被重新注册。

Zookeeper应用场景

1.数据发布与订阅
发布与订阅即所谓的配置管理,顾名思义就是将数据发布到zk节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,地址列表等就非常适合使用。

2.NameService
作为分布式命名服务,通过调用zk的create node api,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。

3.分布通知/协调
ZooKeeper 中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。使用方法通常是不同系统都对 ZK上同一个znode进行注册,监听znode的变化(包括znode本身内容及子节点的),其中一个系统update了znode,那么另一个系统能 够收到通知,并作出相应处理。使用zookeeper来进行分布式通知和协调能够大大降低系统之间的耦合。

4.分布式锁
主要得益于ZooKeeper为我们保证了数据的强一致性,即用户只要完全相信每时每刻,zk集群中任意节点(一个zk server)上的相同znode的数据是一定是相同的。锁服务可以分为两类,一个是保持独占,另一个是控制时序。控制时序中Zk的父节点(/distribute_lock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序。

5.集群管理
1)集群监控:a. 客户端在节点 x 上注册一个Watcher,那么如果x的子节点变化了,会通知该客户端。b. 创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就会消失。
2)Master选举:利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建 /currentMaster 节点,最终一定只有一个客户端请求能够创建成功。

6.分布式队列
一种常规先进先出,另一种待队列成员集齐后执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值