zookeeper是什么

  转载:https://blog.csdn.net/zhangzq86/article/details/80981234html

官方说辞:Zookeeper 分布式服务框架是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中常常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。java

好抽象,咱们改变一下方式,先看看它都提供了哪些功能,而后再看看使用它的这些功能能作点什么。node

ZooKeeper是用于维护配置信息,命名,提供分布式同步和提供组服务的集中式服务。全部这些类型的服务都以某种形式或由分布式应用程序使用。每次实施它们时,都会进行不少工做来修复不可避免的错误和竞争条件。因为难以实现这类服务,所以应用程序一般最初会在其上跳过,从而使它们在存在更改的状况下变得脆弱而且难以管理。即便部署正确,这些服务的不一样实现也会致使管理复杂。程序员

 

官网文档:https://zookeeper.apache.org/doc/current/javaExample.html算法

 

zookeeper提供了什么

 

简单的说,zookeeper=文件系统+通知机制。数据库

一、 文件系统

Zookeeper维护一个相似文件系统的数据结构:apache

 

 

 

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

有四种类型的znode:服务器

一、PERSISTENT-持久化目录节点网络

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

二、 PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点

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

三、EPHEMERAL-临时目录节点

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

四、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点

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

 

二、 通知机制

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

就这么简单,下面咱们看看能作点什么呢?

 

 

咱们能用zookeeper作什么

一、 命名服务

        这个彷佛最简单,在zookeeper的文件系统里建立一个目录,即有惟一的path。在咱们使用tborg没法肯定上游程序的部署机器时便可与下游程序约定好path,经过path即能互相探索发现,不见不散了。

 

二、 配置管理

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

                                         zookeeper简介

 

三、 集群管理

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

        对于第一点,全部机器约定在父目录GroupMembers下建立临时目录节点,而后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的链接断开,其所建立的临时目录节点被删除,全部其余机器都收到通知:某个兄弟目录被删除,因而,全部人都知道:它上船了。新机器加入 也是相似,全部机器收到通知:新兄弟目录加入,highcount又有了。

        对于第二点,咱们稍微改变一下,全部机器建立临时顺序编号目录节点,每次选取编号最小的机器做为master就好。

                                 zookeeper简介

 

四、  分布式锁

        有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务能够分为两类,一个是保持独占,另外一个是控制时序。

        对于第一类,咱们将zookeeper上的一个znode看做是一把锁,经过createznode的方式来实现。全部客户端都去建立 /distribute_lock 节点,最终成功建立的那个客户端也即拥有了这把锁。厕全部言:来也冲冲,去也冲冲,用完删除掉本身建立的distribute_lock 节点就释放出锁。

        对于第二类, /distribute_lock 已经预先存在,全部客户端在它下面建立临时顺序编号目录节点,和选master同样,编号最小的得到锁,用完删除,依次方便。

                                         zookeeper简介

五、队列管理

两种类型的队列:

一、 同步队列,当一个队列的成员都聚齐时,这个队列才可用,不然一直等待全部成员到达。

二、队列按照 FIFO 方式进行入队和出队操做。

第一类,在约定目录下建立临时目录节点,监听节点数目是不是咱们要求的数目。

第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。                 

         终于了解完咱们能用zookeeper作什么了,但是做为一个程序员,咱们老是想狂热了解zookeeper是如何作到这一点的,单点维护一个文件系统没有什么难度,但是若是是一个集群维护一个文件系统保持数据的一致性就很是困难了。

 

分布式与数据复制

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

一、 容错
一个节点出错,不致于让整个系统中止工做,别的节点能够接管它的工做;

二、提升系统的扩展能力
把负载分布到多个节点上,或者增长节点来提升系统的负载能力;

三、提升性能
让客户端本地访问就近的节点,提升用户访问速度。

 

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

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

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

 

        对zookeeper来讲,它采用的方式是写任意。经过增长机器,它的读吞吐能力和响应能力扩展性很是好,而写,随着机器的增多吞吐能力确定降低(这 也是它创建observer的缘由),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,仍是当即复制快速响应。

咱们关注的重点仍是在如何保证数据在集群全部机器的一致性,这就涉及到paxos算法。

 

数据一致性与paxos算法

        听说Paxos算法的难理解与算法的知名度同样使人敬仰,因此咱们先看如何保持数据的一致性,这里有个原则就是:

在一个分布式数据库系统中,若是各节点的初始状态一致,每一个节点都执行相同的操做序列,那么他们最后能获得一个一致的状态。

        Paxos算法解决的什么问题呢,解决的就是保证每一个节点执行相同的操做序列。好吧,这还不简单,master维护一个全局写队列,全部写操做都必须 放入这个队列编号,那么不管咱们写多少个节点,只要写操做是按编号来的,就能保证一致性。没错,就是这样,但是若是master挂了呢。

        Paxos算法经过投票来对写操做进行全局编号,同一时刻,只有一个写操做被批准,同时并发的写操做要去争取选票,只有得到过半数选票的写操做才会被 批准(因此永远只会有一个写操做获得批准),其余的写操做竞争失败只好再发起一轮投票,就这样,在日复一日年复一年的投票中,全部写操做都被严格编号排 序。编号严格递增,当一个节点接受了一个编号为100的写操做,以后又接受到编号为99的写操做(由于网络延迟等不少不可预见缘由),它立刻能意识到本身 数据不一致了,自动中止对外服务并重启同步过程。任何一个节点挂掉都不会影响整个集群的数据一致性(总2n+1台,除非挂掉大于n台)。

总结

        Zookeeper 做为 Hadoop 项目中的一个子项目,是 Hadoop 集群管理的一个必不可少的模块,它主要用来控制集群中的数据,如它管理 Hadoop 集群中的 NameNode,还有 Hbase 中 Master Election、Server 之间状态同步等。

 

Zookeeper工做原理

        ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序能够基于它实现同步服务,配置维护和 命名服务等。Zookeeper是hadoop的一个子项目,其发展历程无需赘述。在分布式应用中,因为工程师不能很好地使用锁机制,以及基于消息的协调 机制不适合在某些应用中使用,所以须要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。Zookeeper的目的就在于此。本文简 单分析zookeeper的工做原理,对于如何使用zookeeper不是本文讨论的重点。

 

 

 

Zookeeper的基本概念

1.1 角色

Zookeeper中的角色主要有如下三类,以下表所示:

                         zookeeper简介

系统模型如图所示:

                         zookeeper简介        

1.2 设计目的

1.最终一致性:client不论链接到哪一个Server,展现给它都是同一个视图,这是zookeeper最重要的性能。

2 .可靠性:具备简单、健壮、良好的性能,若是消息m被到一台服务器接受,那么它将被全部的服务器接受。

3 .实时性:Zookeeper保证客户端将在一个时间间隔范围内得到服务器的更新信息,或者服务器失效的信息。但因为网络延时等缘由,Zookeeper不能保证两个客户端能同时获得刚更新的数据,若是须要最新数据,应该在读数据以前调用sync()接口。

4 .等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每一个client都能有效的等待。

5.原子性:更新只能成功或者失败,没有中间状态。

6 .顺序性:包括全局有序和偏序两种:全局有序是指若是在一台服务器上消息a在消息b前发布,则在全部Server上消息a都将在消息b前被发布;偏序是指若是一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

 ZooKeeper的工做原理

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

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

每一个Server在工做过程当中有三种状态:

  • LOOKING:当前Server不知道leader是谁,正在搜寻
  • LEADING:当前Server即为选举出来的leader
  • FOLLOWING:leader已经选举出来,当前Server与之同步

2.1 选主流程

      当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式须要从新选举出一个新的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会记录事务日志并按期进行快照,方便在恢复时进行状态恢复。选主的具体流程图以下所示:

                                         zookeeper简介

      fast paxos流程是在选举过程当中,某Server首先向全部Server提议本身要成为leader,当其它Server收到提议之后,解决epoch和 zxid的冲突,并接受对方的提议,而后向对方发送接受提议完成的消息,重复这个流程,最后必定能选举出Leader。其流程图以下所示:

                         zookeeper简介

2.2 同步流程

选完leader之后,zk就进入状态同步过程。

        1. leader等待server链接;

        2 .Follower链接leader,将最大的zxid发送给leader;

        3 .Leader根据follower的zxid肯定同步点;

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

        5 .Follower收到uptodate消息后,又能够从新接受client的请求进行服务了。

流程图以下所示:

                                 zookeeper简介

2.3 工做流程

2.3.1 Leader工做流程

Leader主要有三个功能:

        1 .恢复数据;

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

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

        PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是 Follower的对提议的回复,超过半数的Follower经过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。
Leader的工做流程简图以下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。

                                 zookeeper简介

2.3.2 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的工做流程简图以下所示,在实际实现中,Follower是经过5个线程来实现功能的。

                         zookeeper简介

对于observer的流程再也不叙述,observer流程和Follower的惟一不一样的地方就是observer不会参加leader发起的投票。

 

附录:

ZooKeeper典型使用场景一览

        ZooKeeper是一个高可用的分布式数据管理与系统协调框架。基于对Paxos算法的实现,使该框架保证了分布式环境中数据的强一致性,也正是基 于这样的特性,使得zookeeper可以应用于不少场景。网上对zk的使用场景也有很多介绍,本文将结合做者身边的项目例子,系统的对zk的使用场景进 行归类介绍。 值得注意的是,zk并非生来就为这些场景设计,都是后来众多开发者根据框架的特性,摸索出来的典型使用方法。所以,也很是欢迎你分享你在ZK使用上的奇 技淫巧。

       

 
 
 
 
 
 
 
 

场景类别

典型场景描述(ZK特性,使用方法)

应用中的具体使用

数据发布与订阅

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

1. 索引信息和集群中机器节点状态存放在zk的一些指定节点,供各个客户端订阅使用。2. 系统日志(通过处理后的)存储,这些日志一般2-3天后被清除。

 

3. 应用中用到的一些配置信息集中管理,在应用启动的时候主动来获取一次,而且在节点上注册一个Watcher,之后每次配置有更新,实时通知到应用,获取最新配置信息。

4. 业务逻辑中须要用到的一些全局变量,好比一些消息中间件的消息队列一般有个offset,这个offset存放在zk上,这样集群中每一个发送者都能知道当前的发送进度。

5. 系统中有些信息须要动态获取,而且还会存在人工手动去修改这个信息。之前一般是暴露出接口,例如JMX接口,有了zk后,只要将这些信息存放到zk节点上便可。

Name Service

这个主要是做为分布式命名服务,经过调用zk的create node api,可以很容易建立一个全局惟一的path,这个path就能够做为一个名称。

 

分布通知/协调

ZooKeeper 中特有watcher注册与异步通知机制,可以很好的实现分布式环境下不一样系统之间的通知与协调,实现对数据变动的实时处理。使用方法一般是不一样系统都对 ZK上同一个znode进行注册,监听znode的变化(包括znode自己内容及子节点的),其中一个系统update了znode,那么另外一个系统能 够收到通知,并做出相应处理。

1. 另外一种心跳检测机制:检测系统和被检测系统之间并不直接关联起来,而是经过zk上某个节点关联,大大减小系统耦合。2. 另外一种系统调度模式:某系统有控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工做。管理人员在控制台做的一些操做,其实是修改 了ZK上某些节点的状态,而zk就把这些变化通知给他们注册Watcher的客户端,即推送系统,因而,做出相应的推送任务。

 

3. 另外一种工做汇报模式:一些相似于任务分发系统,子任务启动后,到zk来注册一个临时节点,而且定时将本身的进度进行汇报(将进度写回这个临时节点),这样任务管理者就可以实时知道任务进度。

总之,使用zookeeper来进行分布式通知和协调可以大大下降系统之间的耦合。

分布式锁

分布式锁,这个主要得益于ZooKeeper为咱们保证了数据的强一致性,即用户只要彻底相信每时每刻,zk集群中任意节点(一个zk server)上的相同znode的数据是必定是相同的。锁服务能够分为两类,一个是保持独占,另外一个是控制时序。

 

所 谓保持独占,就是全部试图来获取这个锁的客户端,最终只有一个能够成功得到这把锁。一般的作法是把zk上的一个znode看做是一把锁,经过create znode的方式来实现。全部客户端都去建立 /distribute_lock 节点,最终成功建立的那个客户端也即拥有了这把锁。

控 制时序,就是全部视图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了。作法和上面基本相似,只是这里 /distribute_lock 已经预先存在,客户端在它下面建立临时有序节点(这个能够经过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指 定)。Zk的父节点(/distribute_lock)维持一份sequence,保证子节点建立的时序性,从而也造成了每一个客户端的全局时序。

 

集群管理

1. 集群机器监 控:这一般用于那种对集群中机器状态,机器在线率有较高要求的场景,可以快速对集群中机器变化做出响应。这样的场景中,每每有一个监控系统,实时检测集群 机器是否存活。过去的作法一般是:监控系统经过某种手段(好比ping)定时检测每一个机器,或者每一个机器本身定时向监控系统汇报“我还活着”。 这种作法可行,可是存在两个比较明显的问题:1. 集群中机器有变更的时候,牵连修改的东西比较多。2. 有必定的延时。

 

利 用ZooKeeper有两个特性,就能够实时另外一种集群机器存活性监控系统:a. 客户端在节点 x 上注册一个Watcher,那么若是 x 的子节点变化了,会通知该客户端。b. 建立EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过时,那么该节点就会消失。

例 如,监控系统在 /clusterServers 节点上注册一个Watcher,之后每动态加机器,那么就往 /clusterServers 下建立一个 EPHEMERAL类型的节点:/clusterServers/{hostname}. 这样,监控系统就可以实时知道机器的增减状况,至于后续处理就是监控系统的业务了。
2. Master选举则是zookeeper中最为经典的使用场景了。

在 分布式环境中,相同的业务应用分布在不一样的机器上,有些业务逻辑(例如一些耗时的计算,网络I/O处理),每每只须要让整个集群中的某一台机器进行执行, 其他机器能够共享这个结果,这样能够大大减小重复劳动,提升性能,因而这个master选举即是这种场景下的碰到的主要问题。

利用ZooKeeper的强一致性,可以保证在分布式高并发状况下节点建立的全局惟一性,即:同时有多个客户端请求建立 /currentMaster 节点,最终必定只有一个客户端请求可以建立成功。

利用这个特性,就能很轻易的在分布式环境中进行集群选取了。

另外,这种场景演化一下,就是动态Master选举。这就要用到 EPHEMERAL_SEQUENTIAL类型节点的特性了。

上 文中提到,全部客户端建立请求,最终只有一个可以建立成功。在这里稍微变化下,就是容许全部请求都可以建立成功,可是得有个建立顺序,因而全部的请求最终 在ZK上建立结果的一种可能状况是这样: /currentMaster/{sessionId}-1 , /currentMaster/{sessionId}-2 , /currentMaster/{sessionId}-3 ….. 每次选取序列号最小的那个机器做为Master,若是这个机器挂了,因为他建立的节点会立刻小时,那么以后最小的那个机器就是Master了。

1. 在搜索系统中,若是集群中每一个机器都生成一份全量索引,不只耗时,并且不能保证彼此之间索引数据一致。所以让集群中的Master来进行全量索引的生成, 而后同步到集群中其它机器。2. 另外,Master选举的容灾措施是,能够随时进行手动指定master,就是说应用在zk在没法获取master信息时,能够经过好比http方式,向 一个地方获取master。

分布式队列

队列方面,我目前感受有两种,一种是常规的先进先出队列,另外一种是要等到队列成员聚齐以后的才统一按序执行。对于第二种先进先出队列,和分布式锁服务中的控制时序场景基本原理一致,这里再也不赘述。

 

第 二种队列实际上是在FIFO队列的基础上做了一个加强。一般能够在 /queue 这个znode下预先创建一个/queue/num 节点,而且赋值为n(或者直接给/queue赋值n),表示队列大小,以后每次有队列成员加入后,就判断下是否已经到达队列大小,决定是否能够开始执行 了。这种用法的典型场景是,分布式环境中,一个大任务Task A,须要在不少子任务完成(或条件就绪)状况下才能进行。这个时候,凡是其中一个子任务完成(就绪),那么就去 /taskList 下创建本身的临时时序节点(CreateMode.EPHEMERAL_SEQUENTIAL),当 /taskList 发现本身下面的子节点知足指定个数,就能够进行下一步按序进行处理了。

相关文章
相关标签/搜索