zookeeper 集群管理配置集群只能启动一个么

初始ZooKeeper与集群搭建实例_服务器应用_Linux公社-Linux系统门户网站
你好,游客
初始ZooKeeper与集群搭建实例
来源:Linux社区&
作者:dennisit
zookeeper是什么
Zookeeper,一种分布式应用的协作服务,是Google的Chubby一个开源的实现,是的分布式协调服务,它包含一个简单的原语集,应用于分布式应用的协作服务,使得分布式应用可以基于这些接口实现诸如同步、配置维护和分集群或者命名的服务。
zookeeper是一个由多个service组成的集群,一个leader,多个follower,每个server保存一份数据部分,全局数据一致,分布式读写,更新请求转发由leader实施.
更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行,数据更新原子性,一次数据更新要么成功,要么失败,全局唯一数据试图,client无论连接到哪个server,数据试图是一致的.
为什么要用zookeeper
大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等),目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制.协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器,ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用
zookeeper工作原理
zookeeper的核心是原子广播,这个机制保证了各个server之间的同步,实现这个机制的协议叫做Zab协议.Zab协议有两种模式,他们分别是恢复模式和广播模式.
  1.当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导着被选举出来,且大多数server都完成了和leader的状态同步后,恢复模式就结束了.状态同步保证了leader和server具有相同的系统状态.
  2.一旦leader已经和多数的follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态.这时候当一个server加入zookeeper服务中,它会在恢复模式下启动,发下leader,并和leader进行状态同步,待到同步结束,它也参与广播消息.
& & 广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证.所有的提议(proposal)都在被提出的时候加上了zxid.实现中zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch.低32位是个递增计数.
& & 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的server都恢复到一个正确的状态.
& & zookeeper服务一致维持在Broadcast状态,直到leader崩溃了或者leader失去了大部分的followers支持.
& & Broadcast模式极其类似于分布式事务中的2pc(two-phrase commit 两阶段提交):即leader提起一个决议,由followers进行投票,leader对投票结果进行计算决定是否通过该决议,如果通过执行该决议(事务),否则什么也不做.
Leader选举
每个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的请求进行服务了.
zookeeper的数据模型
层次化的目录结构,命名符合常规文件系统规范
每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
节点Znode可以包含数据和子节点,但是EPHEMERAL类型的节点不能有子节点
Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本
客户端应用可以在节点上设置监视器,节点不支持部分读写,而是一次性完整读写
Zoopkeeper 提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而可以设计出多种多样的分布式的数据管理模型
Zookeeper的节点
Znode有两种类型,短暂的(ephemeral)和持久的(persistent)
Znode的类型在创建时确定并且之后不能再修改
短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不可以有子节点
持久znode不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除
Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL.
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,
通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等.
Zookeeper的角色
领导者(leader),负责进行投票的发起和决议,更新系统状态
学习者(learner),包括跟随者(follower)和观察者(observer).
follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
客户端(client),请求发起方
Watcher 在 ZooKeeper 是一个核心功能,Watcher 可以监控目录节点的数据变化以及子目录的变化,一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的 Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应
可以设置观察的操作:exists,getChildren,getData
可以触发观察的操作:create,delete,setData
znode以某种方式发生变化时,&观察&(watch)机制可以让客户端得到通知.
可以针对ZooKeeper服务的&操作&来设置观察,该服务的其他 操作可以触发观察.
比如,客户端可以对某个客户端调用exists操作,同时在它上面设置一个观察,如果此时这个znode不存在,则exists返回 false,如果一段时间之后,这个znode被其他客户端创建,则这个观察会被触发,之前的那个客户端就会得到通知.
Zookeeper集群搭建
Zookeeper 不仅可以单机提供服务,同时也支持多机组成集群来提供服务,实际上Zookeeper还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个Zookeeper实例.
Zookeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够保证服务继续。
集群容灾性:
 3台机器只要有2台可用就可以选出leader并且对外提供服务(2n+1台机器,可以容n台机器挂掉)。
Zookeeper伪分布式环境搭建:
1、去Zookeeper官网下载最新版本的Zookeeper.
[root@localhost zookeeper-cluster]# pwd/export/search/zookeeper-cluster[root@localhost zookeeper-cluster]# lszookeeper-3.4.6.tar.gz[root@localhost zookeeper-cluster]#[root@localhost zookeeper-cluster]# tar -zxvf zookeeper-3.4.6.tar.gz#创建第一个集群节点[root@localhost zookeeper-cluster]# mv zookeeper-3.4.6 zookeeper-3.4.6-node1[root@localhost zookeeper-cluster]# cd zookeeper-3.4.6-node1[root@localhost zookeeper-3.4.6-node1]# pwd/export/search/zookeeper-cluster/zookeeper-3.4.6-node1#创建数据存放路径[root@localhost zookeeper-3.4.6-node1]# mkdir data[root@localhost zookeeper-3.4.6-node1]# cd ../#创建第二第三个集群节点[root@localhost zookeeper-cluster]# cp zookeeper-3.4.6-node1 zookeeper-3.4.6-node2 -R[root@localhost zookeeper-cluster]# cp zookeeper-3.4.6-node1 zookeeper-3.4.6-node3 -R[root@localhost zookeeper-cluster]# lszookeeper-3.4.6-node1& zookeeper-3.4.6-node2& zookeeper-3.4.6-node3& zookeeper-3.4.6.tar.gz[root@localhost zookeeper-cluster]# cd zookeeper-3.4.6-node1/conf/[root@localhost conf]# lsconfiguration.xsl& log4j.properties& zoo_sample.cfg#创建zoo.cfg文件[root@localhost conf]# cp zoo_sample.cfg zoo.cfg
2、配置zoo.cfg文件:
#zookeeper-3.4.6-node1的配置tickTime=2000initLimit=10syncLimit=5clientPort=2181dataDir=/export/search/zookeeper-cluster/zookeeper-3.4.6-node1/dataserver.1=localhost:server.2=localhost:server.3=localhost:
#zookeeper-3.4.6-node2的配置tickTime=2000initLimit=10syncLimit=5clientPort=2182dataDir=/export/search/zookeeper-cluster/zookeeper-3.4.6-node2/dataserver.1=localhost:server.2=localhost:server.3=localhost:
#zookeeper-3.4.6-node3的配置tickTime=2000initLimit=10syncLimit=5clientPort=2183dataDir=/export/search/zookeeper-cluster/zookeeper-3.4.6-node3/dataserver.1=localhost:server.2=localhost:server.3=localhost:
tickTime=2000:tickTime这个时间是作为Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳;
initLimit=10:initLimit这个配置项是用来配置Zookeeper接受客户端(这里所说的客户端不是用户连接Zookeeper服务器的客户端,而是Zookeeper服务器集群中连接到Leader的Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过10个心跳的时间(也就是tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 10*2000=20 秒;
syncLimit=5:syncLimit这个配置项标识Leader与Follower之间发送消息,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是5*2000=10秒;
dataDir=/export/search/zookeeper-cluster/zookeeper-3.4.6-node1/datadataDir顾名思义就是Zookeeper保存数据的目录,默认情况下Zookeeper将写数据的日志文件也保存在这个目录里;
clientPort=2181clientPort这个端口就是客户端连接Zookeeper服务器的端口,Zookeeper会监听这个端口接受客户端的访问请求;
server.1=localhost:server.2=localhost:server.3=localhost:server.A=B:C:D:A是一个数字,表示这个是第几号服务器,B是这个服务器的ip地址C第一个端口用来集群成员的信息交换,表示的是这个服务器与集群中的Leader服务器交换信息的端口D是在leader挂掉时专门用来进行选举leader所用
3、创建ServerID标识
除了修改zoo.cfg配置文件,集群模式下还要配置一个文件myid,这个文件在dataDir目录下,这个文件里面就有一个数据就是A的值,在上面配置文件中zoo.cfg中配置的dataDir路径中创建myid文件
[root@localhost zookeeper-cluster]# cat /export/search/zookeeper-cluster/zookeeper-3.4.6-node1/data/myid1[root@localhost zookeeper-cluster]# cat /export/search/zookeeper-cluster/zookeeper-3.4.6-node2/data/myid22[root@localhost zookeeper-cluster]# cat /export/search/zookeeper-cluster/zookeeper-3.4.6-node3/data/myid3
4、启动zookeeper
[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node1/bin/zkServer.sh startJMX enabled by defaultUsing config: /export/search/zookeeper-cluster/zookeeper-3.4.6-node1/bin/../conf/zoo.cfgStarting zookeeper ... STARTED[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node2/bin/zkServer.sh startJMX enabled by defaultUsing config: /export/search/zookeeper-cluster/zookeeper-3.4.6-node2/bin/../conf/zoo.cfgStarting zookeeper ... STARTED[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node3/bin/zkServer.sh startJMX enabled by defaultUsing config: /export/search/zookeeper-cluster/zookeeper-3.4.6-node3/bin/../conf/zoo.cfgStarting zookeeper ... STARTED
5、检测集群是否启动
[root@localhost zookeeper-cluster]# echo stat|nc localhost 2181[root@localhost zookeeper-cluster]# echo stat|nc localhost 2182[root@localhost zookeeper-cluster]# echo stat|nc localhost 2183#或者[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node1/bin/zkCli.sh[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node2/bin/zkCli.sh[root@localhost zookeeper-cluster]# /export/search/zookeeper-cluster/zookeeper-3.4.6-node3/bin/zkCli.sh
伪集群部署注意事项:
在一台机器上部署了3个server;需要注意的是clientPort这个端口如果在1台机器上部署多个server,那么每台机器都要不同的clientPort.
比如 server.1是2181,server.2是2182,server.3是2183
最后几行唯一需要注意的地方就是
server.X 这个数字就是对应 data/myid中的数字。你在3个server的myid文件中分别写入了1,2,3,那么每个server中的zoo.cfg都配 server.1,server.2,server.3就OK了
--------------------------------------分割线 --------------------------------------
14.04安装分布式存储Sheepdog+ZooKeeper&
6安装sheepdog 虚拟机分布式储存&
ZooKeeper集群配置
使用ZooKeeper实现分布式共享锁
分布式服务框架 ZooKeeper -- 管理分布式环境中的数据
ZooKeeper集群环境搭建实践
ZooKeeper服务器集群环境配置实测
ZooKeeper集群安装
本文永久更新链接地址:
相关资讯 & & &
& (09/09/:16)
& (03/26/:27)
& (03月07日)
& (07/15/:45)
& (02/23/:38)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款Apache Zookeeper 由 Apache Hadoop 的 Zookeeper 子项目发展而来,现已经成为 Apache 的顶级项目,它是一个开放源码的分布式应用程序协调服务,是Google Chubby的一个开源实现。它是一个为分布式应用提供一致性服务的组件,提供的功能包括:配置管理,名字服务,提供分布式同步、队列管理、集群管理等。
使用场景(即上述的功能):,
原理:Zookeeper 从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应,从而实现集群中类似 Master/Slave 管理模式。
Zookeeper有两种运行模式:
1.1、独立模式(standalone mode)
(具体参考:)
只运行在一台服务器上,适合测试环境。
1.2、复制模式(replicated mode)
运行于一个集群上,适合生产环境,这个计算机集群被称为一个&集合体&(ensemble)。
Zookeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够保证服务继续。这跟Zookeeper的复制策略有关:Zookeeper确保对znode树的每一个修改都会被复制到集合体中超过半数的机器上。
由于ZooKeeper集群,会有一个Leader负责管理和协调其他集群服务器,因此服务器的数量通常都是奇数,例如3,5,7...等,这样2n+1的数量的服务器就可以允许最多n台服务器的失效。
(安装可参考:)
这里以zookeeper-3.4.8为例:
1.2.1、下载解压
解压后目录结构为:
├── bin
├── build.xml
├── CHANGES.txt
├── conf
├── contrib
├── dist-maven
├── docs
├── ivysettings.xml
├── ivy.xml
├── lib
├── LICENSE.txt
├── NOTICE.txt
├── README_packaging.txt
├── README.txt
├── recipes
├── src
├── zookeeper-3.4.8.jar
├── zookeeper-3.4.8.jar.asc
├── zookeeper-3.4.8.jar.md5
└── zookeeper-3.4.8.jar.sha1
1.2.2、配置文件
进入conf目录,&cp& zoo_sample.cfg &zoo.cfg &,修改配置文件zoo.cfg为如下:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/usr/local/zookeeper/zookeeper-3.4.8/zk_data
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=192.168.6.131:2888:3888
server.2=192.168.6.132:2888:3888
server.3=192.168.6.133:2888:3888
各配置项的含义:
1. tickTime
= 2000:Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,每隔tickTime时间就会发送一个心跳。
2. initLimit: 配置 Zookeeper 接受客户端(此客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已超过initLimit个tickTime长度后 Zookeeper 服务器还没有收到客户端的返回信息,则表明客户端连接失败。总的时间长度就是 initLimit * tickTime 秒。
3. syncLimit: 配置 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 syncLimit * tickTime 秒
4. dataDir:
Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
5. dataLogDir:若没提供的话则用dataDir。zookeeper的持久化都存储在这两个目录里。dataLogDir里是放到的顺序日志(WAL)。而dataDir里放的是内存数据结构的snapshot,便于快速恢复。为了达到性能最大化,一般建议把dataDir和dataLogDir分到不同的磁盘上,以充分利用磁盘顺序写的特性。
6. clientPort:Zookeeper服务器监听的端口,以接受客户端的访问请求。
7. server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,此端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
每个节点的配置文件都一样。
更多可参考
1.2.3、添加myid文件
除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 上述dataDir 指定的目录下,这个文件里面就只有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。
1.2.4、启动/结束
&bin/zkServer.sh start|start-foreground|stop|restart|status|upgrade|print-cmd&,启动后默认在bin下产生日志文件zookeeper.out
1. 启动ZK服务:
bin/zkServer.sh start
2. 查看ZK服务状态: bin/zkServer.sh status
3. 停止ZK服务:
bin/zkServer.sh stop
4. 重启ZK服务:
bin/zkServer.sh restart
&(启动后在zoo.cfg所指定的dataDir下有version-2文件夹(下有log.1文件)和zookeeper_server.pid文件)
启动后可以借助下面的命令行客户端看是否能连上以确定是否成功启动,也可使用四字命令(如&echo stat|netcat localhost 2181&)快速确定节点状态
2.1、Shell客户端
2.1.1 zk命令
命令行客户端连接ZooKeeper:&./bin/zkCli.sh -server localhost:2181&,连接成功后,会输出 ZooKeeper 的相关环境以及配置信息。并能进行一些操作:
1. 显示根目录下、文件: ls /
使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
2. 显示根目录下、文件: ls2 /
查看当前节点数据并能看到更新次数等数据
3. 创建文件并设置初始内容:create /zk "test" 创建一个新的 znode节点& zk &以及与它关联的字符串
4. 获取文件内容: get /zk
确认 znode 是否包含我们所创建的字符串
5. 修改文件内容: set /zk "zkbak"
对 zk 所关联的字符串进行设置
6. 删除文件: delete /zk
将刚才创建的 znode 删除
7. 删除目录(即使非空):rmr 目录
如可用于删除Kafka的某个Consumer Group
8. 退出客户端: quit
9. 帮助命令: help
客户端连接后,用get / 命令可以发现此时只有zookeeper一项;如果此Zookeeper用于对Kafka或JStorm等提供服务,则还会有相应的其他目录。
2.1.2 四字命令
此外,也可通过四字命令更方便地获取服务端信息,&四字命令的用法为&echo 四字命令|netcat localhost 2181&,常用的四字命令如下:
conf:输出Zookeeper服务器配置的详细信息
cons:输出所有连接到服务器的客户端的完全的连接/会话的详细信息。包括&接收/发送&的包数量、会话ID、操作延迟、最后的操作执行等
dump:输出未经处理的会话和临时节点
envi:输出关于服务器运行环境的详细信息
reqs:输出未经处理的请求
ruok:测试服务是否处于正确状态。若是则会返回&imok&,否则不做任何反应
stat:输出关于性能和连接的客户端的列表。(通过此命令也可查看节点是leader还是follower)
wchs:输出服务器watch的详细信息
wchc:通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表
wchp:通过路径列出服务器watch的详细信息,它输出一个与session相关的路径
mntr:输出一些Zookeeper运行时信息,通过对这些返回结果的解析可以达到监控效果
2.2、Java客户端
使用Java进行Zookeeper的CRUD操作,示例如下:
1 package cn.edu.buaa.act.test.TestZ
3 import java.io.IOE
5 import org.apache.zookeeper.CreateM
6 import org.apache.zookeeper.KeeperE
7 import org.apache.zookeeper.W
8 import org.apache.zookeeper.ZooDefs.I
9 import org.apache.zookeeper.ZooK
* 此类包含两个主要的 ZooKeeper 函数,分别为 createZKInstance ()和 ZKOperations ()。&br&
* (1)createZKInstance ()函数负责对 ZooKeeper 实例 zk 进行初始化。 ZooKeeper 类有两个构造函数,我们这里使用
* & ZooKeeper ( String connectString, , int sessionTimeout, , Watcher watcher
* )&对其进行初始化。因此,我们需要提供初始化所需的,连接字符串信息,会话超时时间,以及一个 watcher 实例。&br&
* (2)ZKOperations ()函数是我们所定义的对节点的一系列操作。它包括:创建 ZooKeeper
* 节点、查看节点、修改节点数据、查看修改后节点数据、删除节点、查看节点是否存在。另外,需要注意的是:在创建节点的时候,需要提供节点的名称、数据、
* 权限以及节点类型。此外,使用 exists 函数时,如果节点不存在将返回一个 null 值。
24 public class ZookeeperTest {
// 会话超时时间,设置为与系统默认时间一致
private static final int SESSION_TIMEOUT = 30000;
// 创建 ZooKeeper 实例
// 创建 Watcher 实例
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
System.out.println("event=" + event.toString());
// 初始化 ZooKeeper 实例
private void createZKInstance() throws IOException {
zk = new ZooKeeper("192.168.6.131:.6.132:.6.133:2181", ZookeeperTest.SESSION_TIMEOUT,
private void ZKOperations() throws IOException, InterruptedException, KeeperException {
System.out.println("\n 创建 ZooKeeper 节点 (znode : zoo2, 数据: myData2 ,权限: OPEN_ACL_UNSAFE ,节点类型: Persistent");
zk.create("/zoo2", "myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("\n 查看是否创建成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("\n 修改节点数据 ");
zk.setData("/zoo2", "shenlan211314".getBytes(), -1);
System.out.println("\n 查看是否修改成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("\n 删除节点 ");
zk.delete("/zoo2", -1);
System.out.println("\n 查看节点是否被删除: ");
System.out.println(" 节点状态: [" + zk.exists("/zoo2", false) + "]");
private void ZKClose() throws InterruptedException {
zk.close();
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZookeeperTest dm = new ZookeeperTest();
dm.createZKInstance();
dm.ZKOperations();
dm.ZKClose();
相关Maven依赖:
&dependency&
&groupId&com.101tec&/groupId&
&artifactId&zkclient&/artifactId&
&version&0.2&/version&
&/dependency&
3、Zookeeper dashboard
4.1 数据及日志维护
  Zookeeper的数据文件存放在配置中指定的dataDir中,每个数据文件名都以snapshot开头,每个数据文件为zookeeper某个时刻数据全量快照。在zookeeper中,对数据的更新操作,包括创建节点、更新节点内容、删除节点都会记录事务日志;客户端对ZK的更新操作都是永久的,不可回退的。为做到这点,ZK会将每次更新操作以事务日志的形式写入磁盘,写入成功后才会给予客户端响应。zookeeper在完成若干次事务日志(snapCount)后会生成一次快照,把当前zk中的所有节点的状态以文件的形式dump到硬盘中,生成一个snapshot文件。这里的事务次数是可以配置,默认是100000个。&
  Zookeeper的日志包括两个部分,一部分是系统日志,另一部分是事务日志。
  系统日志使用log4j进行管理,conf目录中有一个log4j配置文件,该配置文件默认没有打开滚动输出,需要用户自己配置,具体请参看log4j介绍。
  事务日志默认存放在dataDir中,当然可以使用dataLogDir指定存放的位置。正常运行过程中,针对所有更新操作,在返回客户端&更新成功&的响应前,ZK会确保已经将本次更新操作的事务日志写到磁盘上,只有这样,整个更新操作才会生效。每触发一次数据快照,就会生成一个新的事务日志。
  默认情况下,zk不会自动清理数据文件和日志文件,因此需要管理员自己清理。我们可以使用ZK的工具类PurgeTxnLog进行清理,当然,我们也可以写脚本自己维护,同时可以使用工具慢慢清理,避免占用大量IO。清理脚本如下:
务必注意:
  如果长时间不清理,切忌同一时间使用rm命令同时删除大量文件,这样会造成IO利用率瞬间飙升,zookeeper的连接会出现断连或session超时,影响现网业务使用。
  另外,对于每一个数据文件,它都是某一时刻的完整快照,我们可以定时将该文件备份,方便对数据进行还原或将zookeeper直接迁移到另外一个集群。
4.2 数据清理
具体详见:
4.3 可视化事务日志
具体详见:
Zookeeper运行久了产生的日志和事务数据非常大,在我们的实践中甚至由于从没清理导致磁盘满了,虽然Zookeeper节点没死,但ZK UI监控上显示出&This instance is not serviceing requests&。由于Zookeeper不能提供服务,JStorm节点就死了,Kafka节点也无法提供服务(没死),清理数据后就好了。
上述参考资料里列出了几种方法,我们采取定时自动清理的做法(每次留10个),写如下脚本,加入crontab定期执行:
#snapshot file dir
dataDir=/usr/local/zookeeper/zookeeper-3.4.8/zk_data/version-2
#tran log dir
dataLogDir=/usr/local/zookeeper/zookeeper-3.4.8/zk_data/version-2
#zk log dir
#Leave 10 files
count=$[$count+1]
ls -t $dataLogDir/log.* | tail -n +$count | xargs rm -f
ls -t $dataDir/snapshot.* | tail -n +$count | xargs rm -f
4.4 权限控制
具体参见:&和&
4.5 Zookeeper应用场景及实践
经典应用:
1)NameService
不多说,本身就是一个共享的树形文件系统
2)配置管理
不同的process watch 自己的配置znode, 当配置变化可以收到通知
3)集群membership管理
集群节点下,每个server对应一个EPHEMERAL的节点,节点名就是server name/ IP,当它和zookeeper的心跳断了,对应的节点被删除,并且所有集群内的节点可以收到新的child List,保证每个server都知道进群内的其他server
4) master选举
和3)类似,但是节点换成EPHEMERAL_SEQUENTIAL的,大家都约定以当前编号最小的server做为master。当master挂了,每个server都会被通知到一份新的server 列表,大家都把编号最小的那个作为master
5) 分布式独占锁
类似Java synchronized的语义 在约定的锁节点上创建EPHEMERAL_SEQUENTIAL节点作为等待队列,如果编号最小的就是自己就获得锁,否则wait()住。获得锁的process通过删除自己的节点释放锁,这样每个等待的process会得到通知,在事件处理函数里判断自己是不是最小的编号,如果是则唤醒之前wait住的线程,这样本进程就获得了锁
6)barrier屏障
意思是所有相关的process都到达齐了再往下执行。实现方法,也是在barrier节点创建EPHEMERAL_SEQUENTIAL的节点,每个process都会得到变化后的children list,当大小为barrier要求数的时候,各个process继续执行。 zookeeper作为分布式process协调的中介,本身是一个单点failure点,所以它本身也做为一个集群,通常部署2n + 1台, 客户端连接不同的zookeeper server,但是得到视图是一样的,这点是zookeeper内部保证的
Zookeeper客户端主要有原生客户端、zclient、Apache Curator等。
以下代码使用Zookeeper原生的客户端(Zookeeper源码里),推荐使用更方便的客户端&
4.5.1 配置管理
1 package cn.edu.buaa.act.test.TestZ
3 import java.io.IOE
5 import org.apache.zookeeper.CreateM
6 import org.apache.zookeeper.KeeperE
7 import org.apache.zookeeper.W
8 import org.apache.zookeeper.ZooK
9 import org.apache.zookeeper.ZooDefs.I
* &h1&配置管理&/h1&&br/&
* Zookeeper很容易实现集中式的配置管理:&br/&
* 比如将APP1的所有配置配置到/APP1
* node下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法Watcher.
* 那么在zookeeper上/APP1
* znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",
* false,null));
* @author zsm Email:
* @date Sep 13, :08 PM
* @version 1.0
* @parameter
34 public class ManageConfiguration {
private static final int SESSION_TIMEOUT = 30000;
private static final String zookeeperAddr = "192.168.6.131:.6.132:.6.133:2181";
private static final String znodePath = "/zsm_dbIP";
private ZooK
public ManageConfiguration() throws KeeperException, InterruptedException, IOException {
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
System.out.println("db ip changed,new value:" + new String(zk.getData(znodePath, true, null)));
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 初始化 ZooKeeper 实例,初始化时提供的Watcher就会触发一次
zk = new ZooKeeper(zookeeperAddr, SESSION_TIMEOUT, wh);
// 为了确保节点存在,不存在则先创建
if (zk.exists(znodePath, false) == null) {
zk.create(znodePath, "192.168.0.7".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("节点不存在,新建节点:" + znodePath + "=" + new String(zk.getData(znodePath, true, null)));
public static void main(String[] args) throws InterruptedException, KeeperException, IOException {
new ManageConfiguration();
while (true) {
4.5.2 集群管理
1 package cn.edu.buaa.act.test.TestZ
3 import java.io.IOE
5 import org.apache.zookeeper.CreateM
6 import org.apache.zookeeper.KeeperE
7 import org.apache.zookeeper.W
8 import org.apache.zookeeper.ZooDefs.I
9 import org.apache.zookeeper.ZooK
* &h1&集群管理&/h1& &br/&
* 在 Zookeeper 上创建一个 EPHEMERAL 类型的节点,然后每个 Server 在它们创建目录节点的父目录节点上调用getChildren(String path, boolean watch) 方法并设置 watch 为 true
* 由于是 EPHEMERAL 目录节点,当创建它的 Server 死去,这个目录节点也随之被删除,所以 Children 将会变化,这时
* getChildren上的 Watch 将会被调用,所以其它 Server 就知道已经有某台 Server 死去了。新增 Server 同理。
* 若创建的是EPHEMERAL_SEQUENTIAL 节点,节点名会自动被append上一个唯一编号。可以在节点加入或删除触发wh时取编号最小的作为Leader,实现master选举
* @author zsm
* @date Sep 13, :08 PM
* @version 1.0
* @parameter
34 public class ManageCluster {
private static final int SESSION_TIMEOUT = 30000;
private static final String zookeeperAddr = "192.168.6.131:.6.132:.6.133:2181";
private static final String znodePath = "/zsm_Nodes";
private ZooK
public ManageCluster(String thisNodeID) throws IOException, KeeperException, InterruptedException {
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
// System.out.println("*********wh1:event=" + event.toString() +
// " ********");
System.out.println("节点变化,现有所有节点:" + zk.getChildren(znodePath, true));
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 初始化 ZooKeeper 实例,初始化时提供的Watcher就会触发一次
zk = new ZooKeeper(zookeeperAddr, SESSION_TIMEOUT, wh);
{// 根节点不存在的话创建PERSISTENT根节点
if (zk.exists(znodePath, null) == null) {
zk.create(znodePath, "root node".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 创建EPHEMERAL_SEQUENTIAL节点
zk.create(znodePath + "/" + thisNodeID, thisNodeID.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 在父节点getChildren,true
zk.getChildren(znodePath, true);
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (args.length & 0) {
System.out.println("args length is &0.");
System.exit(1);
new ManageCluster(args[0]);
while (true) {
4.5.3 分布式同步锁、队列等
1 package cn.edu.buaa.act.test.TestZ
3 import java.io.IOE
4 import java.util.A
5 import java.util.L
7 import org.apache.zookeeper.CreateM
8 import org.apache.zookeeper.KeeperE
9 import org.apache.zookeeper.W
10 import org.apache.zookeeper.ZooDefs.I
11 import org.apache.zookeeper.ZooK
* 分布式共享锁,与通过Zookeeper管理Cluster类似,只是每次触发Watcher后的操作,取现有所有节点后有下一步操作: 若最小节点等于当前节点,
* 则获得锁.
* 如果所有节点的nodeid都一样,则各节点优先级一样,先进先得到锁;若不同节点的nodeid不能一样.则nodeid越小优先级越大
* @author zsm
* @date 日 下午10:15:24
* @version 1.0
* @parameter
32 public class T3_ManageLocks {
private static final int SESSION_TIMEOUT = 5000;
private static final String zookeeperAddr = "192.168.6.131:.6.132:.6.133:2181";
private static final String znodePath = "/zsm_Locks";
private ZooK
private static String thisNodeID;
public T3_ManageLocks(String thisNodeID) throws IOException, KeeperException, InterruptedException {
T3_ManageLocks.thisNodeID = thisNodeID;
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
// System.out.println("*********wh1:event=" + event.toString() +
// " ********");
List&String& nodeListTmp = zk.getChildren(znodePath, true);
System.out.println("节点变化,现有所有节点:" + nodeListTmp);
String[] nodeList = nodeListTmp.toArray(new String[nodeListTmp.size()]);
Arrays.sort(nodeList);
String nodeIdWithLock = new String(zk.getData(znodePath + "/" + nodeList[0], null, null));
System.out.println("curnode: " + T3_ManageLocks.thisNodeID + "
node with lock: " + nodeIdWithLock);
if (nodeIdWithLock.equals(T3_ManageLocks.thisNodeID)) {
System.out.println("当前节点 " + nodeIdWithLock + " 获得锁");
// do something then System.exit(0);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 初始化 ZooKeeper 实例,初始化时提供的Watcher就会触发一次
zk = new ZooKeeper(zookeeperAddr, SESSION_TIMEOUT, wh);
{// 根节点不存在的话创建PERSISTENT根节点
if (zk.exists(znodePath, null) == null) {
zk.create(znodePath, "root node".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 创建EPHEMERAL_SEQUENTIAL节点
zk.create(znodePath + "/" + thisNodeID, thisNodeID.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 在父节点getChildren,true
// zk.getChildren(znodePath, true);
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (args.length & 0) {
System.out.println("args length is &0.");
System.exit(1);
new T3_ManageLocks(args[0]);
while (true) {
5、参考资料
1、(安装)
2、(Zookeeper系列)
3、(使用和原理探究)
4、(全。腾讯大数据之Zookeeper运营经验分享)
阅读(...) 评论()
Welcome user from}

我要回帖

更多关于 zookeeper集群搭建 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信