ZooKeeper入门指南

  • Getting Started: Coordinating Distributed Applications with ZooKeeper
  • Pre-requisites
  • Download
  • Standalone Operation
  • Managing ZooKeeper Storage
  • Connecting to ZooKeeper
  • Programming to ZooKeeper
  • Running Replicated ZooKeeper
  • Other Optimizations



入门:使用Zookeeper协调分布式应用


该文档的内容能够使你学会快速使用Zookeeper.文档主要针对希望尝试它的开发人员,它包含如何安装一个单机Zookeeper服务的安装说明,一些验证正在运行的命令,一个简单编程例子. 最后,为了方便,关于一些复杂的安装,例如集群运行部署,优化事务日志.关于商业的完整安装文档,请参考 ZooKeeper Administrator's Guide.



知识储备

查看用户指南中的系统要求.



下载

从Apache镜像中下载一个最新稳定的版本.



单机配置

安装单机Zookeeper是非常简单的. 服务包含一个独立的Jar文件,所以只需要创一个配置文件.

一旦你下载了稳定的Zookeeper版本,解压它并使用cd去根目录使用一个配置文件启动它. 这是一个例子,创建在 conf/zoo.cfg:

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181

这个文件可以被称为任何名称,但是为了能够说明那它就称它为conf/zoo.cfg. 可以通过改变dataDir的值 去指明一个存在的目录. 这儿是每一个字段的含义:


tickTime


tickTime是最基本的时间单元,使用毫秒为时间单位.它被使用来作为心跳检测和最小的会话超时时间,是tickTime时间的两倍.

dataDir


这个地址用来存储内存数据库的快照,除非特别声明,事务文件也会存储在该位置.


clientPort


这个端口用来监听连接客户端连接.

现在你已经创建了配置文件,你可以开启Zookeeper.

bin/zkServer.sh start


ZooKeeper日志信息使用log4j  -- 在程序员指南日志部分有更多详细信息.你将会看到日志文件输出到控制台(默认配置)或者在log4j配置日志文件地址查看.

主要讲单机模式运行Zookeeper的步骤. 这里没有使用集群配置,所以如果Zookeeper一旦出现处理异常,服务将会停止.这对于大部分情况下都是可以接收的,如果要在集群环境下运行,请查看 Running Replicated ZooKeeper.


管理Zookeeper存储

对于正式长时间运行的Zookeeper存储系统必须进行外部管理(数据文档和日志).查阅更多详细信息,请查看维护部分.



连接Zookeeper

$ bin/zkCli.sh -server 127.0.0.1:2181



这个操作执行很简单,看起来像是文件操作.

只要你已经连接了Zookeeper,你看到下面这些信息:

Connecting to localhost:2181
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
Welcome to ZooKeeper!
JLine support is enabled
[zkshell: 0]


来到shell,输入help你可以获得一个可以在客户端执行的命令清单,例如:


[zkshell: 0] help
ZooKeeper host:port cmd args
        get path [watch]
        ls path [watch]
        set path data [version]
        delquota [-n|-b] path
        quit
        printwatches on|off
        createpath data acl
        stat path [watch]
        listquota path
        history
        setAcl path acl
        getAcl path
        sync path
        redo cmdno
        addauth scheme auth
        delete path [version]
        setquota -n|-b val path

由此,你可以尝试一些简单的命令来熟悉命令行接口. First, start by issuing the list command, as in ls, yielding:


[zkshell: 8] ls / [zookeeper]


接下来,接下来通过create /zk_test my_data创建一个新的节点. 创建的新节点包含一个String类型的节点数据.你可以看到如下这样:

[zkshell: 9] create /zk_test my_data
Created /zk_test


可以通过ls命令查看目录下节点,例如:

[zkshell: 11] ls /
[zookeeper, zk_test]


现在zk_test已经被创建.

接下来,运行get命令验证znode的数据关联.例如:


[zkshell: 12] get /zk_test
my_data
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 5
mtime = Fri Jun 05 13:57:06 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0
dataLength = 7
numChildren = 0

我们可以执行set命令改变zk_test节点的关联数据,例如:

[zkshell: 14] set /zk_test junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0
[zkshell: 15] get /zk_test
junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0


(我们在设置数据后,获取该数据验证,发现确实发生了改变,最后让我们来删除该节点.)


[zkshell: 16] delete /zk_test
[zkshell: 17] ls /
[zookeeper]
[zkshell: 18]

以上内容到这里为止.如果需要查阅文档更多的剩余内容,请查看Programmer's Guide.



ZooKeeper编程

ZooKeeper可以使用Java语言和C语言两种编程方式. 它们是功能等价的.C语言仅有两个不通电:单线程和多线程.这个不同点只会在消息循环时提现出来.更多信息,请查看 Programming Examples in the ZooKeeper Programmer's Guide 使用不同API的例子.



运行集群Zookeeper

运行单机Zookeeper有利于方便的评估、开发、测试.但在正式环境,应该运行集群Zookeeper. 同一个应用的服务组我们称之为集群. 在集群模式下,所有服务都可以复制同样的配置.



注意



在集群模式,至少应有3台服务器,强烈推荐你使用奇数个服务器.如果你仅有两台服务器,一旦其中一台出现故障,你讲没有足够的机器组成集群.两台机器比一台机器天生就有更多的不稳定的可能,因为存在两个故障点.



集群模式和单机模式都需要使用的conf/zoo.cfg文件,但是有一些地方不一样.例子:


tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

新配置条目, initLimit 是集群中其他机器连接leader的超时时间限制.syncLimit是一个服务器无法访问leader的最大时间限制.

这两个时间限制值,都是基于时间单元tickTime值设置的.例如,initLimit是5 tick,在tick值是2000毫秒的情况下,该值是10秒.

上面的配置文件中的表单服务条目(指server.1=zoo1:2888:3888,server.2=zoo2:2888:3888,server.3=zoo3:2888:3888这些配置).由server.X组成Zookeeper服务.当服务启动时,会通过查找zookeeper/data目录下的myid文件,来查找它属于那个服务. 这个文件包含一个ASCCII编码的服务编号.

最后,需要注意每个服务名称后面都会跟两个端口号:" 2888" 和 "3888". 服务器之间通过前一个端口号互相连接.因为各个服务器间需要互相通信,所以相互连接是必要的,例如用来协调服务更新顺序. 更确切的解释是,一个Zookeeper服务通过该端口连接follower至leader. 当一个新的leader产生时,follower使用该端口打开TCP连接leader.因为默认的leader选举也使用TCP,我们一般为leader选举使用另外一个端口,这就是服务条目中的第二个端口的作用.



注意事项



如果你想要在一台服务器是运行集群服务,可以在每个服务配置文件的server.X中,将集群的servername设置为localhost & 设置各个(例如:i.e. 2888:3888, 2889:3889, 2890:3890),各个服务的dataDirs和clientPort必须独立.  (在上面的集群配置例子中,虽然在同一台localhost机器上运行集群,但你仍然需要三个配置文件).

请注意,在一台机器上运行集群不会有冗余效果.如果发生意外情况导致机器挂掉,全部Zookeeper服务都将挂掉.完全冗余效果需要每一个服务都有属于自己的服务器.并且必须是独立的物理服务器.单台物理机器上的多个虚拟机同样也会容易因种种意外造成服务全部挂掉.



其他优化

还有一些其他配置能够大大提高性能:

  • 为了获得服务更新的低延迟,建立专门的事物日志目录是必要的.默认的事物日志目录与数据快照和myid文件是同一个目录.dataLogDir 参数用于设置新的事物日志目录.
  • [tbd: 其他配置参数还有那些?]