Zookeeper集群的安装和使用
Apache Zookeeper 由 Apache Hadoop 的 Zookeeper 子项目发展而来,现已经成为 Apache 的顶级项目,它是一个开放源码的分布式应用程序协调服务,是Google Chubby的一个开源实现。它是一个为分布式应用提供一致性服务的组件,提供的功能包括:配置管理,名字服务,提供分布式同步、队列管理、集群管理等。
使用场景(即上述的功能):典型应用场景篇一,典型应用场景篇二
原理:Zookeeper 从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应,从而实现集群中类似 Master/Slave 管理模式。
1、安装
Zookeeper有两种运行模式:
1.1、独立模式(standalone mode)
(具体参考:http://blog.****.net/csfreebird/article/details/44006453)
只运行在一台服务器上,适合测试环境。
1.2、复制模式(replicated mode)
运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble)。
Zookeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够保证服务继续。这跟Zookeeper的复制策略有关:Zookeeper确保对znode树的每一个修改都会被复制到集合体中超过半数的机器上。
由于ZooKeeper集群,会有一个Leader负责管理和协调其他集群服务器,因此服务器的数量通常都是奇数,例如3,5,7...等,这样2n+1的数量的服务器就可以允许最多n台服务器的失效。
(安装可参考:http://blog.****.net/csfreebird/article/details/44007295)
这里以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为如下:
各配置项的含义:
每个节点的配置文件都一样。
更多可参考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、使用
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操作,示例如下:
相关Maven依赖:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.2</version>
</dependency>
3、Zookeeper dashboard
GitHub Zookeeper UI Dashboard
4、进阶
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 数据清理
具体详见:http://nileader.blog.51cto.com/1381108/932156
4.3 可视化事务日志
具体详见:http://nileader.blog.51cto.com/1381108/926753
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=10 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 权限控制
具体参见:使用super身份对有权限的节点进行操作 和 ZooKeeper权限控制
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源码里),推荐使用更方便的客户端 Curator
4.5.1 配置管理
4.5.2 集群管理
4.5.3 分布式同步锁、队列等
5、参考资料
1、http://blog.****.net/csfreebird/article/details/43984425(安装)
2、http://www.cnblogs.com/yuyijq/p/3424473.html(Zookeeper系列)
3、http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html(使用和原理探究)
4、http://data.qq.com/article?id=2863(全。腾讯大数据之Zookeeper运营经验分享)