Zookeeper那些事

1、 什么是Zookeeper

Zookeeper 是 Google 的 Chubby一个开源的实现,是 Hadoop 的分布式协调服务java

它包含一个简单的原语集,分布式应用程序能够基于它实现同步服务,配置维护和命名服务等node

 

 

2、  为何使用Zookeeper?

大部分分布式应用须要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)算法

目前,大部分应用须要开发私有的协调程序,缺少一个通用的机制apache

协调程序的反复编写浪费,且难以造成通用、伸缩性好的协调器服务器

ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用网络

3、  Zookeeper能帮咱们作什么?

Hadoop2.0,使用Zookeeper的事件处理确保整个集群只有一个活跃的NameNode,存储配置信息等.session

HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储访问控制列表等.数据结构

4、Zookeeper的特性

Zookeeper是简单的分布式

Zookeeper是富有表现力的oop

Zookeeper具备高可用性

Zookeeper采用松耦合交互方式

Zookeeper是一个资源库

5、Zookeeper的安装和配置(单机模式)

一、下载ZooKeeper:

http://labs.renren.com/apache-mirror/zookeeper/zookeeper-3.4.3/zookeeper-3.4.3.tar.gz

解压:tar xzf zookeeper-3.4.3.tar.gz/2

二、在conf目录下建立一个配置文件zoo.cfg

  1. tickTime=2000  
  2. dataDir=/Users/zdandljb/zookeeper/data  
  3. dataLogDir=/Users/zdandljb/zookeeper/dataLog          
  4.   
  5. clientPort=2181  

三、启动ZooKeeper的Server

sh bin/zkServer.sh start, 若是想要关闭,输入:zkServer.sh stop

6、Zookeeper的安装和配置(集群模式)

一、建立myid文件:

server1机器的内容为:1

server2机器的内容为:2

server3机器的内容为:3

二、在conf目录下建立一个配置文件zoo.cfg

  1. tickTime=2000  
  2. dataDir=/Users/zdandljb/zookeeper/data  
  3. dataLogDir=/Users/zdandljb/zookeeper/dataLog          
  4.   
  5. clientPort=2181                                  
  6.   
  7. initLimit=5                                       
  8.   
  9. syncLimit=2                                                 
  10.   
  11. server.1=server1:2888:3888                                      
  12.   
  13. server.2=server2:2888:3888                                     
  14.   
  15. server.3=server3:2888:3888  

7、Zookeeper的安装和配置(伪集群模式)

一、建了3个文件夹,server1 server2 server3,而后每一个文件夹里面解压一个zookeeper的下载包

二、进入data目录,建立一个myid的文件,里面写入一个数字,server1,就写一个1,server2对应myid文件就写入2,server3对应myid文件就写个3

三、在conf目录下建立一个配置文件zoo.cfg

 
  1. tickTime=2000  
  2.        dataDir=/Users/zdandljb/zookeeper/data  
  3.        dataLogDir=xxx/zookeeper/server1/           
  4.   
  5. clientPort=2181                                             
  6.   
  7. initLimit=5                                       
  8.   
  9. syncLimit=2                                                
  10.   
  11. server.1=server1:2888:3888                              
  12.   
  13. server.2=server2:2888:3888                                    
  14.   
  15. server.3=server3:2888:3888  

8、Zookeeper的数据模型

层次化的目录结构,命名符合常规文件系统规范

每一个节点在zookeeper中叫作znode,而且其有一个惟一的路径标识

节点Znode能够包含数据和子节点,可是EPHEMERAL类型的节点不能有子节点

Znode中的数据能够有多个版本,好比某一个路径下存有多个数据版本,那么查询这个路径下的数据就须要带上版本

客户端应用能够在节点上设置监视器

节点不支持部分读写,而是一次性完整读写

9、Zookeeper的节点

Znode有两种类型,短暂的(ephemeral)和持久的(persistent)

Znode的类型在建立时肯定而且以后不能再修改

短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不能够有子节点

持久znode不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除

Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL

10、Zookeeper的角色

领导者(leader),负责进行投票的发起和决议,更新系统状态

学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并向客户端返回结果,在选主过程当中参与投票Observer能够接受客户端链接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提升读取速度

客户端(client),请求发起方

11、Zookeeper的顺序号

建立znode时设置顺序标识,znode名称后会附加一个值

顺序号是一个单调递增的计数器,由父节点维护

在分布式系统中,顺序号能够被用于为全部的事件进行全局排序,这样客户端能够经过顺序号推断事件的顺序

12、Zookeeper的读写机制

Zookeeper是一个由多个server组成的集群

一个leader,多个follower

每一个server保存一份数据副本

全局数据一致

分布式读写

更新请求转发,由leader实施

十3、Zookeeper的保证

更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行

数据更新原子性,一次数据更新要么成功,要么失败

全局惟一数据视图,client不管链接到哪一个server,数据视图都是一致的

实时性,在必定事件范围内,client能读到最新数据

十4、Zookeeper的API接口

  1. String create(String path, byte[] data,List<ACL> acl, CreateMode createMode)  
  2.   
  3. Stat exists(String path, boolean watch)  
  4.   
  5. void delete(String path, int version)  
  6.   
  7. List<String> getChildren(String path, boolean watch)  
  8.   
  9. List<String> getChildren(String path, boolean watch)  
  10.   
  11. Stat setData(String path, byte[] data, int version)  
  12.   
  13. byte[] getData(String path, boolean watch, Stat stat)  
  14.   
  15. void addAuthInfo(String scheme, byte[] auth)  
  16.   
  17. Stat setACL(String path, List<ACL> acl,int version)  
  18.   
  19. List<ACL> getACL(String path, Stat stat)   

十5、观察(watcher)

Watcher 在 ZooKeeper 是一个核心功能,Watcher 能够监控目录节点的数据变化以及子目录的变化,一旦这些状态发生变化,服务器就会通知全部设置在这个目录节点上的 Watcher,从而每一个客户端都很快知道它所关注的目录节点的状态发生变化,而作出相应的反应

能够设置观察的操做:exists,getChildren,getData

能够触发观察的操做:create,delete,setData

十六写操做与zookeeper内部事件的对应关系

 

 

十7、zookeeper内部事件与watcher的对应关系

 

 

十8、 写操做与watcher的对应关系

 

 

十9、ACL

每一个znode被建立时都会带有一个ACL列表,用于决定谁能够对它执行何种操做

 

身份验证模式有三种:

digest:用户名,密码

host:经过客户端的主机名来识别客户端

ip: 经过客户端的ip来识别客户端

new ACL(Perms.READ,newId("host","example.com"));

                   这个ACL对应的身份验证模式是host,符合该模式的身份是example.com,权限的组合是:READ

二10、Znode的节点状态

 

每一个ACL都是身份验证模式、符合该模式的一个身份和一组权限的组合

二11、 Zookeeper工做原理

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

一旦leader已经和多数的follower进行了状态同步后,他就能够开始广播消息了,即进入广播状态。这时候当一个server加入zookeeper服务中,它会在恢复模式下启动,发现leader,并和leader进行状态同步。待到同步结束,它也参与消息广播。Zookeeper服务一直维持在Broadcast状态,直到leader崩溃了或者leader失去了大部分的followers支持。

广播模式须要保证proposal被按顺序处理,所以zk采用了递增的事务id号(zxid)来保证。全部的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch。低32位是个递增计数。

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式须要从新选举出一个新的leader,让全部的server都恢复到一个正确的状态。

二12、Leader选举

首先看一下选举的过程,zk的实现中用了基于paxos算法(主要是fastpaxos)的实现。具体以下;此外恢复模式下,若是是从新刚从崩溃状态恢复的或者刚启动的的server还会从磁盘快照中恢复数据和会话信息。(zk会记录事务日志并按期进行快照,方便在恢复时进行状态恢复)

每一个Server启动之后都询问其它的Server它要投票给谁。

对于其余server的询问,server每次根据本身的状态都回复本身推荐的leader的id和上一次处理事务的zxid(系统启动时每一个server都会推荐本身)

收到全部Server回复之后,就计算出zxid最大的哪一个Server,并将这个Server相关信息设置成下一次要投票的Server。

计算这过程当中得到票数最多的的sever为获胜者,若是获胜者的票数超过半数,则改server被选为leader。不然,继续这个过程,直到leader被选举出来。

leader就会开始等待server链接

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

Leader根据follower的zxid肯定同步点

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

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


 

Observing: 观察状态,这时候observer会观察leader是否有改变,而后同步leader的状态;Following:  跟随状态,接收leader的proposal ,进行投票。并和leader进行状态同步

 

 

Looking: 寻找状态,这个状态不知道谁是leader,会发起leader选举;Leading:    领导状态,对Follower的投票进行决议,将状态和follower进行同步

二十3、Zookeeper示例代码

 

输出的结果以下:

已经触发了 None 事件!

testRootData   [testChildPathOne]

目录节点状态:[5,5,1281804532336,1281804532336,0,1,0,0,12,1,6]

已经触发了NodeChildrenChanged 事件!

testChildDataTwo

已经触发了NodeDeleted 事件!

已经触发了NodeDeleted 事件!

二十4、应用场景

应用场景1: 统一命名服务

n  分布式应用中,一般须要有一套完整的命名规则,既可以产生惟一的名称又便于人识别和记住,一般状况下用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,既对人友好又不会重复。

n  Name Service 是 Zookeeper 内置的功能,只要调用 Zookeeper 的 API 就能实现

应用场景2: 配置管理

n  配置的管理在分布式应用环境中很常见,例如同一个应用系统须要多台 PCServer 运行,可是它们运行的应用系统的某些配置项是相同的,若是要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样很是麻烦并且容易出错。

n  将配置信息保存在 Zookeeper 的某个目录节点中,而后将全部须要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,而后从 Zookeeper 获取新的配置信息应用到系统中。

Zookeeper很容易实现这种集中式的配置管理,好比将APP1的全部配置配置到/APP1 znode下,APP1全部机器一启动就对/APP1这个节点进行监控(zk.exist(“/APP1″,true)),而且实现回调方法 Watcher,那么在zookeeper上/APP1 znode节点下数据发生变化的时候,每一个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据便可 (zk.getData(“/APP1″,false,null));

 

 

应用场景3: 集群管理

n  Zookeeper 可以很容易的实现集群管理的功能,若有多台 Server 组成一个服务集群,那么必需要一个“总管”知道当前集群中每台机器的服务状态,一旦有机器不能提供服务,集群中其它集群必须知道,从而作出调整从新分配服务策略。一样当增长集群的服务能力时,就会增长一台或多台 Server,一样也必须让“总管”知道。

n  Zookeeper 不只可以维护当前的集群中机器的服务状态,并且可以选出一个“总管”,让这个总管来管理集群,这就是 Zookeeper 的另外一个功能 Leader Election。

应用集群中,咱们经常须要让每个机器知道集群中(或依赖的其余某一个集群)哪些机器是活着的,而且在集群机器由于宕机,网络断链等缘由可以不在人工介入的状况下迅速通知到每个机器。Zookeeper一样很容易实现这个功能,好比我在zookeeper服务器端有一个znode叫/APP1SERVERS,那么集群中每个机器启动 的时候都去这个节点下建立一个EPHEMERAL类型的节点,好比server1建立/APP1SERVERS/SERVER1(可使用ip,保证不重 复),server2建立/APP1SERVERS/SERVER2,而后SERVER1和SERVER2都watch /APP1SERVERS这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行watch的客户端。由于EPHEMERAL类型节 点有一个很重要的特性,就是客户端和服务器端链接断掉或者session过时就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,而后集群中全部对/APP1SERVERS进行watch的客户端都会收到通知,而后取得最新列表便可。

 

 

Zookeeper 如何实现 Leader Election,也就是选出一个 Master Server;另外有一个应用场景就是集群选master,一旦master挂掉可以立刻能从slave中选出一个master,实现步骤和前者同样,只是机器在启动的 时候在APP1SERVERS建立的节点类型变为EPHEMERAL_SEQUENTIAL类型,这样每一个节点会自动被编号

  1. zk.create("/testRootPath/testChildPath1","1".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  2.   
  3. zk.create(“/testRootPath/testChildPath2”,“2”.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  4.   
  5. zk.create("/testRootPath/testChildPath3","3".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  6.   
  7. zk.create("/testRootPath/testChildPath4","4".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  8.   
  9. System.out.println(zk.getChildren("/testRootPath",false));  
  10.   
  11. 打印结果:[testChildPath10000000000,testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]  

规定编号最小的为master,因此当咱们对SERVERS节点作监控的时候,获得服务器列表,只要全部集群机器逻辑认为最小编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,而后新的服务器列表就被推送到客户端,而后每一个节点逻辑认为最小编号节点为master,这样就作到动态master选举。

应用场景4:共享锁

共享锁在同一个进程中很容易实现,可是在跨进程或者在不一样 Server 之间就很差实现了。Zookeeper 却很容易实现这个功能,实现方式也是须要得到锁的 Server 建立一个 EPHEMERAL_SEQUENTIAL 目录节点,而后调用 getChildren方法获取当前的目录节点列表中最小的目录节点是否是就是本身建立的目录节点,若是正是本身建立的,那么它就得到了这个锁,若是不是那么它就调用 exists(String path, boolean watch) 方法并监控 Zookeeper 上目录节点列表的变化,一直到本身建立的节点是列表中最小编号的目录节点,从而得到锁,释放锁很简单,只要删除前面它本身所建立的目录节点就好了。


 

应用场景5: 队列管理

Zookeeper 能够处理两种类型的队列:当一个队列的成员都聚齐时,这个队列才可用,不然一直等待全部成员到达,这种是同步队列;队列按照 FIFO 方式进行入队和出队操做,例如实现生产者和消费者模型

建立一个父目录 /synchronizing,每一个成员都监控目录 /synchronizing/start 是否存在,而后每一个成员都加入这个队列(建立/synchronizing/member_i 的临时目录节点),而后每一个成员获取 / synchronizing 目录的全部目录节点,判断 i 的值是否已是成员的个数,若是小于成员个数等待 /synchronizing/start 的出现,若是已经相等就建立 /synchronizing/start。

 

二十5、总结

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

Zoopkeeper提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而能够设计出多种多样的分布式的数据管理模型

转载:http://blog.csdn.net/l1028386804/article/details/52226265

相关文章
相关标签/搜索