【Zookeeper系列一】Zookeeper应用介绍与安装部署

#0 系列目录#java

#1 Zookeeper概述# ZooKeeper是一个为分布式应用所设计的分布的、开源的协调服务,它主要是用来解决分布式应用中常常遇到的一些数据管理问题,简化分布式应用协调及其管理的难度,提供高性能的分布式服务。ZooKeeper自己能够以Standalone模式安装运行,不过它的长处在于经过分布式ZooKeeper集群(一个Leader,多个Follower),基于必定的策略来保证ZooKeeper集群的稳定性和可用性,从而实现分布式应用的可靠性

在网上看到了一个很不错的关于ZooKeeper的介绍: 顾名思义动物园管理员,他是拿来管大象(Hadoop) 、 蜜蜂(Hive) 、 小猪(Pig) 的管理员, Apache Hbase和 Apache Solr 以及LinkedIn sensei 等项目中都采用到了 Zookeeper。ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,ZooKeeper是以Fast Paxos算法为基础,实现同步服务,配置维护和命名服务等分布式应用

从介绍能够看出,ZooKeeper更倾向于对大型应用的协同维护管理工做。IBM则给出了IBM对ZooKeeper的认知: Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中常常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等

总之,我认为它的核心词就是一个单词,协调

#2 Zookeeper特征# 在Hadoop权威指南中看到了关于ZooKeeper的一些核心特征,阅读以后感受总结的甚是精辟,在这里引用并总结。

##2.1 简易## ZooKeeper的最重要核心就是一个精简文件系统,提供一些简单的操做以及附加的抽象(例如排序和通知)。

##2.2 易表达## ZooKeeper的原型是一个丰富的集合,它们是一些已建好的块,能够用来构建大型的协做数据结构和协议,例如:分布式队列、分布式锁以及一组对等体的选举。

##2.3 高可用性## ZooKeeper运行在一些集群上,被设计成可用性较高的,所以应用程序能够依赖它。ZooKeeper能够帮助你的系统避免单点故障,从而创建一个可靠的应用程序

##2.4 松散耦合## ZooKeeper的交互支持参与者之间并不了解对方。例如:ZooKeeper能够被当作一种公共的机制,使得进程彼此不知道对方的存在也能够相互发现而且交互,对等方可能甚至不是同步的。

这一特色我感受最能体如今集群的部署启动过程当中。像Hadoop当把配置文件写好以后,而后运行启动脚本,则251,241,242中做为集群的虚拟机是同步启动的,也就是DataNode,NameNode,TaskTracker,以及JobTracker的启动并运行时在一次启动过程当中启动的,就是运行一次启动脚本文件,则都启动起来。可是ZooKeeper的启动过程却不是这样的。我在251,241,242部署了ZooKeeper集群,并进行启动,则启动的过程是这样的:首先ssh到251而后启动,这时候251的集群节点启动起来,可是控制台一直报错,大概的含义就是没有检测到其余两个结点。接着分别ssh到241,242,分别启动集群中的剩下的结点,当241启动起来时,回到251查看,发现报错的信息减小,意思是只差一个结点。当251,241,242三台服务器的结点所有启动起来,则三台的服务器的控制台打印出正常的信息

##2.5 一个库## ZooKeeper提供了一个开源的、共享的执行存储,以及通用协做的方法,分担了每一个程序员写通用协议的负担。随着时间的推移,人们能够增长和改进这个库来知足本身的需求。

#3 为何使用Zookeeper# 记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),全部集群中的服务器经过Chubby最终选出一个Master Server ,最后这个Master Server来协调工做。简单来讲其原理就是:在一个分布式系统中,有一组服务器在运行一样的程序,它们须要肯定一个Value,以那个服务器提供的信息为主/为准,当这个服务器通过n/2+1的方式被选出来后,全部的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,你们以他提供的信息为准。很想知道Google Chubby中的奥妙,惋惜人家Google不开源,自家用。

可是在2009年3年之后沉默已久的Yahoo在Apache上推出了相似的产品ZooKeeper,而且在Google原有Chubby的设计思想上作了一些改进,由于ZooKeeper并非彻底遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:

输入图片说明

ZooKeeper跟Chubby同样用来存放一些相互协做的信息(Coordination),这些信息比较小通常不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中

当有事件致使node数据,例如:变动,增长,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),若是有watcher,会触发其process方法,执行process方法中的业务逻辑,如图:

输入图片说明

##3.1 应用实例## ZooKeeper有了上述的这些用途,让咱们设想一下,在一个分布式系统中有这这样的一个应用:

2个任务工厂(Task Factory)一主一从,若是从的发现主的死了之后,从的就开始工做,他的工做就是向下面不少台代理(Agent)发送指令,让每台代理(Agent)得到不一样的帐户进行分布式并行计算,而每台代理(Agent)中将分配不少账号,若是其中一台代理(Agent)死掉了,那么这台死掉的代理上的帐户就不会继续工做了。上述,出现了3个最主要的问题:

  1. Task Factory 主/从一致性的问题
  2. Task Factory 主/从心跳如何用简单+稳定 或者2者折中的方式实现
  3. 一台代理(Agent)死掉了之后,一部分的帐户就没法继续工做,须要通知全部在线的代理(Agent)从新分配一次账号

输入图片说明

OK,让咱们想一想ZooKeeper是否是能帮助咱们去解决目前遇到的这3个最主要的问题呢?

  1. 任务工厂Task Factory都链接到ZooKeeper上,建立节点,设置对这个节点进行监控,监控方法例如:
event= new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, "/TaskFactory");

这个方法的意思就是只要Task Factory与zookeeper断开链接后,这个节点就会被自动删除

  1. 原来主的任务工厂断开了TCP链接,这个被建立的/TaskFactory节点就不存在了,并且另一个链接在上面的Task Factory能够马上收到这个事件(Event),知道这个节点不存在了,也就是说主TaskFactory死了。

  2. 接下来另一个活着的TaskFactory会再次建立/TaskFactory节点,而且写入本身的ip到znode里面,做为新的标记。

  3. 此时Agents也会知道主的TaskFactory不工做了,为了防止系统中大量的抛出异常,他们将会先把本身手上的事情作完,而后挂起,等待收到Zookeeper上从新建立一个/TaskFactory节点,收到 EventType.NodeCreated 类型的事件将会继续工做

  4. 原来从的TaskFactory 将本身变成一个主TaskFactory,当系统管理员启动原来死掉的主的TaskFactory,世界又恢复平静了。

  5. 若是一台代理死掉,其余代理他们将会先把本身手上的事情作完,而后挂起,向TaskFactory发送请求,TaskFactory会从新分配(sharding)账户到每一个Agent上了,继续工做。

上述内容,大体如图所示:

输入图片说明

#4 Zookeeper基本知识# ##4.1 层次化的名字空间## ZooKeeper的整个名字空间的结构是层次化的,和通常的Linux文件系统结构很是类似,一颗很大的树。这也就是ZooKeeper的数据结构状况。名字空间的层次由斜杠/来进行分割,在名称空间里面的每个结点的名字空间惟一由这个结点的路径来肯定。

每个节点拥有自身的一些信息,包括:数据、数据长度、建立时间、修改时间等等。从这样一类既含有数据,又做为路径表标示的节点的特色中,能够看出,ZooKeeper的节点既能够被看作是一个文件,又能够被看作是一个目录,它同时具备两者的特色。为了便于表达,从此咱们将使用Znode来表示所讨论的ZooKeeper节点

##4.2 Znode## Znode维护着数据、ACL(access control list,访问控制列表)、时间戳等交换版本号等数据结构,它经过对这些数据的管理来让缓存生效而且令协调更新。每当Znode中的数据更新后它所维护的版本号将增长,这很是相似于数据库中计数器时间戳的操做方式。

另外Znode还具备原子性操做的特色:命名空间中,每个Znode的数据将被原子地读写。读操做将读取与Znode相关的全部数据,写操做将替换掉全部的数据。除此以外,每个节点都有一个访问控制列表,这个访问控制列表规定了用户操做的权限。

ZooKeeper中一样存在临时节点。这些节点与session同时存在,当session生命周期结束,这些临时节点也将被删除。临时节点在某些场合也发挥着很是重要的做用。

##4.3 Watch机制## Watch机制就和单词自己的意思同样,看。看什么?具体来说就是某一个或者一些Znode的变化。官方给出的定义:一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们

Watch机制主要有如下三个特色:

  1. 一次性的触发器(one-time trigger)

当数据改变的时候,那么一个Watch事件会产生而且被发送到客户端中。可是客户端只会收到一次这样的通知,若是之后这个数据再次发生改变的时候,以前设置Watch的客户端将不会再次收到改变的通知,由于Watch机制规定了它是一个一次性的触发器

当设置监视的数据发生改变时,该监视事件会被发送到客户端,例如,若是客户端调用了 getData("/znode1", true) 而且稍后 /znode1 节点上的数据发生了改变或者被删除了,客户端将会获取到 /znode1 发生变化的监视事件,而若是 /znode1 再一次发生了变化,除非客户端再次对 /znode1 设置监视,不然客户端不会收到事件通知

  1. 发送给客户端(Sent to the client)

这个代表了Watch的通知事件是从服务器发送给客户端的,是异步的,这就代表不一样的客户端收到的Watch的时间可能不一样,可是ZooKeeper有保证:当一个客户端在看到Watch事件以前是不会看到结点数据的变化的。例如:A=3,此时在上面设置了一次Watch,若是A忽然变成4了,那么客户端会先收到Watch事件的通知,而后才会看到A=4。

Zookeeper 客户端和服务端是经过 Socket 进行通讯的,因为网络存在故障,因此监视事件颇有可能不会成功地到达客户端,监视事件是异步发送至监视者的,Zookeeper 自己提供了保序性(ordering guarantee):即客户端只有首先看到了监视事件后,才会感知到它所设置监视的 znode 发生了变化(a client will never see a change for which it has set a watch until it first sees the watch event). 网络延迟或者其余因素可能致使不一样的客户端在不一样的时刻感知某一监视事件,可是不一样的客户端所看到的一切具备一致的顺序

  1. 被设置Watch的数据(The data for which the watch was set)

这意味着 znode 节点自己具备不一样的改变方式。你也能够想象 Zookeeper 维护了两条监视链表:数据监视和子节点监视(data watches and child watches) getData() and exists() 设置数据监视getChildren() 设置子节点监视。 或者,你也能够想象 Zookeeper 设置的不一样监视返回不一样的数据,getData() 和 exists() 返回 znode 节点的相关信息,而 getChildren() 返回子节点列表。所以, setData() 会触发设置在某一节点上所设置的数据监视(假定数据设置成功),而一次成功的 create() 操做则会出发当前节点上所设置的数据监视以及父节点的子节点监视一次成功的 delete() 操做将会触发当前节点的数据监视和子节点监视事件,同时也会触发该节点父节点的child watch

Zookeeper 中的监视是轻量级的,所以容易设置、维护和分发。当客户端与 Zookeeper 服务器端失去联系时,客户端并不会收到监视事件的通知,只有当客户端从新链接后,若在必要的状况下,之前注册的监视会从新被注册并触发,对于开发人员来讲 这一般是透明的。只有一种状况会致使监视事件的丢失,即:经过 exists() 设置了某个 znode 节点的监视,可是若是某个客户端在此 znode 节点被建立和删除的时间间隔内与 zookeeper 服务器失去了联系,该客户端即便稍后从新链接 zookeeper服务器后也得不到事件通知

##4.4 ACL访问控制列表## 这是另一个和Linux操做系统很是类似的地方,ZooKeeper使用ACL来控制对旗下Znode结点们的访问。ACL的实现和Linux文件系统的访问权限十分相似:它经过设置权限为来代表是否容许对一个结点的相关内容的改变

可是与传统Linux机制不太相同,一个结点的数据没有相似“拥有者,组用户,其余用户”的概念,在ZooKeeper中,ACL经过设置ID以及与其关联的权限来完成访问控制的。ACL的权限组成语法是:

(scheme:expression, perms)

前者代表设置的ID,逗号后面表示的是ID相关的权限,例如:

(ip:172.16.16.1,READ)

指明了IP地址为如上的用户的权限为只读。

如下列举如下ACL所具备的权限:

CREATE:代表你能够建立一个Znode的子结点。
READ:你能够获得这个结点的数据以及列举该结点的子结点状况。
WRITE:设置一个结点的数据。
DELETE:能够删除一个结点
ADMIN:对一个结点设置权限。

#5 Zookeeper部署# ZooKeeper的部署方式主要有三种,单机模式、伪集群模式、集群模式。其实剩下的两种模式都是集群模式的特殊状况。

##5.1 系统环境## 输入图片说明

##5.2 下载Zookeeper##

  1. mkdir /home/taomk/zk 建立文件夹

  2. cd /home/taomk/zk; wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz 下载

  3. tar xvf zookeeper-3.4.6.tar.gz 解压缩

  4. mv zookeeper-3.4.6 zookeeper346 重命名

  5. cd zookeeper346; ls -l

输入图片说明

##5.3 配置环境变量##

export ZOOKEEPER_HOME=/home/taomk/zk/zookeeper346
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf

##5.4 ZooKeeper的单机模式部署## ZooKeeper的单机模式一般是用来快速测试客户端应用程序的,在实际过程当中不多是单机模式。单机模式的配置也比较简单。

  1. 编写配置文件zoo.cfg:ZooKeeper的运行默认是读取zoo.cfg文件里面的内容的。
~mkdir /home/taomk/zk/zoo/zk0
~cp conf/zoo_sample.cfg conf/zk0.cfg
~vim conf/zk0.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/conan/zoo/zk0
clientPort=2181

在zk0.cfg这个文件中,咱们须要指定 dataDir 的值,它指向了一个目录,这个目录在开始的时候须要为空。下面是每一个参数的含义:

tickTime :基本事件单元,以毫秒为单位。这个时间是做为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每一个 tickTime 时间就会发送一个心跳。

dataDir :存储内存中数据库快照的位置,顾名思义就是 Zookeeper 保存数据的目录,默认状况下,Zookeeper 将写数据的日志文件也保存在这个目录里

clientPort :这个端口就是客户端链接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

使用单机模式时用户须要注意:这种配置方式下没有 ZooKeeper 副本,因此若是 ZooKeeper 服务器出现故障, ZooKeeper 服务将会中止

  1. 启动Zookeeper
~bin/zkServer.sh start zk0.cfg

输入图片说明

zk的服务显示为QuorumPeerMain

~jps
5321 QuorumPeerMain
5338 Jps

查看运行状态

~bin/zkServer.sh status zk0.cfg
JMX enabled by default
Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk0.cfg
Mode: standalone

单节点的时,Mode会显示为standalone。

  1. 中止ZooKeeper服务
~ bin/zkServer.sh stop zk0.cfg
JMX enabled by default
Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk0.cfg
Stopping zookeeper ... STOPPED

##5.5 ZooKeeper的伪集群模式部署## 所谓 “伪分布式集群” 就是在,在一台PC中,启动多个ZooKeeper的实例。“彻底分布式集群” 是每台PC,启动一个ZooKeeper实例。其实在企业中式不会存在的,另外为了测试一个客户端程序也没有必要存在,只有在物质条件比较匮乏的条件下才会存在的模式。集群伪分布模式就是在单机下模拟集群的ZooKeeper服务,在一台机器上面有多个ZooKeeper的JVM同时运行

ZooKeeper的集群模式下,多个Zookeeper服务器在工做前会选举出一个Leader,在接下来的工做中这个被选举出来的Leader死了,而剩下的Zookeeper服务器会知道这个Leader死掉了,在活着的Zookeeper集群中会继续选出一个Leader,选举出Leader的目的是为了能够在分布式的环境中保证数据的一致性。

  1. 确认集群服务器的数量

因为ZooKeeper集群中,会有一个Leader负责管理和协调其余集群服务器,所以服务器的数量一般都是单数,例如3,5,7...等,这样2n+1的数量的服务器就能够容许最多n台服务器的失效

  1. 建立环境目录
~ mkdir /home/taomk/zk/zoo/zk1
~ mkdir /home/taomk/zk/zoo/zk2
~ mkdir /home/taomk/zk/zoo/zk3

#新建myid文件
~ echo "1" > /home/taomk/zk/zoo/zk1/myid
~ echo "2" > /home/taomk/zk/zoo/zk2/myid
~ echo "3" > /home/taomk/zk/zoo/zk3/myid
  1. 分别修改配置文件

修改:dataDir,clientPort

增长:集群的实例,server.X,”X”表示每一个目录中的myid的值

~ vim /home/taomk/zk/zookeeper346/conf/zk1.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/taomk/zk/zoo/zk1
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

~ vim /home/taomk/zk/zookeeper346/conf/zk2.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/taomk/zk/zoo/zk2
clientPort=2182
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

~ vim /home/taomk/zk/zookeeper346/conf/zk3.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/taomk/zk/zoo/zk3
clientPort=2183
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户链接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中链接到 Leader 的 Follower 服务器初始化链接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器尚未收到客户端的返回信息,那么代表这个客户端链接失败。总的时间长度就是 10*2000=20 秒。

syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 5*2000=10 秒。

server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器,就是集群模式下配置的myid文件所存放的数值;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,须要一个端口来从新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通讯的端口若是是伪集群的配置方式,因为 B 都是同样,因此不一样的 Zookeeper 实例通讯端口号不能同样,因此要给它们分配不一样的端口号

因为三个服务都在同一台电脑上,所以这里要保证地址的惟一性,所以要特别注意IP地址和端口号不要互相冲突,以避免影响程序的正确执行。

3个节点的ZooKeeper集群配置完成,接下来咱们的启动服务。

  1. 启动集群
~ bin/zkServer.sh start zk1.cfg
~ bin/zkServer.sh start zk2.cfg
~ bin/zkServer.sh start zk3.cfg

~ jps
5422 QuorumPeerMain
5395 QuorumPeerMain
5463 QuorumPeerMain
5494 Jps

#查看节点状态
~ bin/zkServer.sh status zk1.cfg
JMX enabled by default
Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk1.cfg
Mode: follower

~ bin/zkServer.sh status zk2.cfg
JMX enabled by default
Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk2.cfg
Mode: leader

~ bin/zkServer.sh status zk3.cfg
JMX enabled by default
Using config: /home/taomk/zk/zookeeper346/bin/../conf/zk3.cfg
Mode: follower
  1. 查看ZooKeeper物理文件目录结构
~ tree -L 3 /home/taomk/zk/zoo

输入图片说明

##5.6 ZooKeeper Distributed模式## ZooKeeper分布式模式安装(ZooKeeper集群)也比较容易,这里说明一下基本要点。

首先要明确的是,ZooKeeper集群是一个独立的分布式协调服务集群,“独立”的含义就是说,若是想使用ZooKeeper实现分布式应用的协调与管理,简化协调与管理,任何分布式应用均可以使用,这就要归功于Zookeeper的数据模型(Data Model)和层次命名空间(Hierarchical Namespace)结构,在设计你的分布式应用协调服务时,首要的就是考虑如何组织层次命名空间。

下面说明分布式模式的安装配置,过程以下所示:

  1. 第一步:主机名称到IP地址映射配置

ZooKeeper集群中具备两个关键的角色:Leader和Follower。集群中全部的结点做为一个总体对分布式应用提供服务,集群中每一个结点之间都互相链接,因此,在配置的ZooKeeper集群的时候,每个结点的host到IP地址的映射都要配置上集群中其它结点的映射信息

例如,ZooKeeper集群中每一个结点的配置,以slave-01为例,/etc/hosts内容以下所示:

192.168.0.179   slave-01  
192.168.0.178   slave-02  
192.168.0.177   slave-03

ZooKeeper采用一种称为Leader election的选举算法。在整个集群运行过程当中,只有一个Leader,其余的都是Follower,若是ZooKeeper集群在运行过程当中Leader出了问题,系统会采用该算法从新选出一个Leader。所以,各个结点之间要可以保证互相链接,必须配置上述映射。

ZooKeeper集群启动的时候,会首先选出一个Leader,在Leader election过程当中,某一个知足选举算法的结点就能成为Leader。

  1. 第二步:修改ZooKeeper配置文件

在其中一台机器(slave-01)上,解压缩zookeeper-3.3.4.tar.gz,修改配置文件conf/zoo.cfg,内容以下所示:

tickTime=2000  
dataDir=/home/hadoop/storage/zookeeper  
clientPort=2181  
initLimit=5  
syncLimit=2  
server.1=slave-01:2888:3888  
server.2=slave-02:2888:3888  
server.3=slave-03:2888:3888
  1. 第三步:远程复制分发安装文件

上面已经在一台机器slave-01上配置完成ZooKeeper,如今能够将该配置好的安装文件远程拷贝到集群中的各个结点对应的目录下:

cd /home/hadoop/installation/  
scp -r zookeeper-3.3.4/ hadoop@slave-02:/home/hadoop/installation/  
scp -r zookeeper-3.3.4/ hadoop@slave-03:/home/hadoop/installation/
  1. 第四步:设置myid

在咱们配置的dataDir指定的目录下面,建立一个myid文件,里面内容为一个数字,用来标识当前主机,conf/zoo.cfg文件中配置的server.X中X为何数字,则myid文件中就输入这个数字,例如:

hadoop@slave-01:~/installation/zookeeper-3.3.4$ echo "1" > /home/hadoop/storage/zookeeper/myid  
hadoop@slave-02:~/installation/zookeeper-3.3.4$ echo "2" > /home/hadoop/storage/zookeeper/myid  
hadoop@slave-03:~/installation/zookeeper-3.3.4$ echo "3" > /home/hadoop/storage/zookeeper/myid
  1. 第五步:启动ZooKeeper集群

在ZooKeeper集群的每一个结点上,执行启动ZooKeeper服务的脚本,以下所示:

hadoop@slave-01:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start  
hadoop@slave-02:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start  
hadoop@slave-03:~/installation/zookeeper-3.3.4$ bin/zkServer.sh start

启动的顺序是slave-01>slave-02>slave-03,因为ZooKeeper集群启动的时候,每一个结点都试图去链接集群中的其它结点,先启动的确定连不上后面还没启动的,因此日志前面部分的异常是能够忽略的。经过后面部分能够看到,集群在选出一个Leader后,最后稳定了。其余结点可能也出现相似问题,属于正常。

#6 Zookeeper命令行操做# ZooKeeper命令行工具相似于Linux的shell环境,不过功能确定不及shell啦,可是使用它咱们能够简单的对ZooKeeper进行访问,数据建立,数据修改等操做。

对于客户端来讲,ZooKeeper是一个总体(ensemble),链接到ZooKeeper集群实际上感受在独享整个集群的服务,因此,你能够在任何一个结点上创建到服务集群的链接。

当启动 ZooKeeper 服务成功以后,输入下述命令,链接到 ZooKeeper 服务:

~ bin/zkCli.sh –server 127.0.0.1:2181

链接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息,并在屏幕输出“ Welcome to ZooKeeper ”等信息。

命令行工具的一些简单操做以下:

  1. 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
ls /

输入图片说明

  1. 建立一个新的 znode ,使用 create /zk myData 。这个命令建立了一个新的 znode 节点“ zk ”以及与它关联的字符串:
create /zk "myData"

输入图片说明

  1. 运行 get 命令来确认 znode 是否包含咱们所建立的字符串:
get /zk

输入图片说明

  1. 经过 set 命令来对 zk 所关联的字符串进行设置
set /zk "zsl"
get /zk

输入图片说明

  1. znode 删除
delete /zk
  1. 经过help打印命令行帮助

输入图片说明

  1. 退出客户端链接
quit

#7 Java编程现实命令行操做#

  1. ZkDemo.java
public class ZkDemo {

    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        // 建立一个与服务器的链接
        ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 60000, new Watcher() {
            // 监控全部被触发的事件
            public void process(WatchedEvent event) {
                System.out.println("EVENT:" + event.getType());
            }
        });

        // 查看根节点
        System.out.println("ls / => " + zk.getChildren("/", true));

        // 建立一个目录节点
        if (zk.exists("/node", true) == null) {
            zk.create("/node", "conan".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println("create /node conan");
            // 查看/node节点数据
            System.out.println("get /node => " + new String(zk.getData("/node", false, null)));
            // 查看根节点
            System.out.println("ls / => " + zk.getChildren("/", true));
        }

        // 建立一个子目录节点
        if (zk.exists("/node/sub1", true) == null) {
            zk.create("/node/sub1", "sub1".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println("create /node/sub1 sub1");
            // 查看node节点
            System.out.println("ls /node => " + zk.getChildren("/node", true));
        }

        // 修改节点数据
        if (zk.exists("/node", true) != null) {
            zk.setData("/node", "changed".getBytes(), -1);
            // 查看/node节点数据
            System.out.println("get /node => " + new String(zk.getData("/node", false, null)));
        }

        // 删除节点
        if (zk.exists("/node/sub1", true) != null) {
            zk.delete("/node/sub1", -1);
            zk.delete("/node", -1);
            // 查看根节点
            System.out.println("ls / => " + zk.getChildren("/", true));
        }

        // 关闭链接
        zk.close();
    }
}
  1. pom.xml,maven配置文件
<dependencies>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.6</version>
        <exclusions>
            <exclusion>
                <groupId>javax.jms</groupId>
                <artifactId>jms</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jdmk</groupId>
                <artifactId>jmxtools</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jmx</groupId>
                <artifactId>jmxri</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
相关文章
相关标签/搜索