一 应用场景描述
目前在测试豌豆荚的Codis作为Redis的集群部署方案,但是Codis2.0目前依赖于Zookeeper作为配置信息的存放和同步工具。在接触Zookeeper之前只是看过一些文档和资料大概知道很多公司使用Zookeeper作为配置数据同步和管理的中间件。
二 Zookeeper原理
按照ZooKeeper官方的说法,ZooKeeper是一个用于维护配置信息,命名空间,提供分布式同步和分组服务的一个中央服务协调工具。
设计目标Design Goals
ZooKeeper很简单
ZooKeeper允许分布式程序相互之间通过一个共享的类似标准文件系统的层级命名空间进行协调工作。这个命名空间由多个数据寄存器组成,又叫做znodes。和典型的文件系统不同的是,ZooKeeper的数据是保存到内存中的,而文件系统上的数据是保存到磁盘上的,这样ZooKeeper可以达到更高的吞吐量和较低的延迟。
ZooKeeper可以复制
和ZooKeeper协调的分布式程序一样,ZooKeeper本身设计就是可以在一组主机间进行复制。组成ZooKeeper服务的服务器必须相互之间知道彼此。他们维护一个ZooKeeper服务状态的内存镜像,日志和快照信息存储在磁盘上。只要大部分服务器可用,ZooKeeper服务就可用。
客户端连接到单个ZooKeeper服务器,维护一个用于发送请求,获得响应,获得watch事件和发送心跳的TCP连接。如果这个TCP连接断了,这个客户端将连接到另一个不同的服务器。
ZooKeeper是有序的
ZooKeeper用一个数字来标记每个更新来反映所有事务的序列号。后续操作可以使用这个序列号来实现更高层面的抽象概念,比如同步原因。
ZooKeeper很快
ZooKeeper在读操作为主导的应用中速度更快。
数据模型和层级命令空间
ZooKeeper的命名空间很像一个标准的文件系统。不像标准的文件系统那样,ZooKeeper命令空间的每个节点和子节点都可以关联数据。使用znode这个术语来表示ZooKeeper的数据节点
Conditional updates and watches
ZooKeeper支持watches的概念。客户端可以在一个znode上设置一个watch。当这个znode改变时,在它上设置的watch也会被触发和移除。
Guaranters
ZooKeeper非常快和简单。因为它的设计目标是成为例如同步这些更复杂服务的基础组件,所以它提供一系列的保证措施。
Sequential Consistency序列号一致性 客户端的更新会根据它们发送的顺序
Atomicity原子性 要么更新失败要么更新成功
Single System Image 无论客户端连接到哪个ZooKeeper服务端得到的数据都是一样的
Reliability 一旦一个更新被提交,它将一直保持更新的状态直到更新被重写
Timeliness
三 ZooKeeper部署和管理
1.依赖软件
ZooKeeper需要JDK1.6以上,最好将ZooKeeper部署到不同的机器上。
2.设置ZooKeeper集群
为了搭建可靠的ZooKeeper服务,应该部署ZooKeeper集群,又叫做ensemble集合。只要集合中大部分成员可用,那么整个ZooKeeper服务就可用。集合中的成员数量必须是奇数个。
wget tar zxvf zookeeper-3.4.6.tar.gz cd zookeeper-3.4.6 cp conf/zoo_sample.cfg conf/zoo.cfg
zoo.cfg的内容如下
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/tmp/zookeeper clientPort=2181 autopurge.snapRetainCount=500 autopurge.purgeInterval=24 server.1=zookeeper1:2888:3888 server.2=zookeeper2:2888:3888 server.3=zookeeper3:2888:3888
tickTime 单个计时时间长短,ZooKeeper的基本时间单位,以毫秒为单位。用于常规先跳检测和超时
initLimit 允许followers连接并同步到leader的时间总量,如果ZooKeeper管理的数据量比较大就增大这个值
syncLimit 允许followers向leader同步的时间总量
dataDir 指定ZooKeeper相关数据存放路径
dataLogDir 如果设置这个参数那么存放日志到这个参数指定的目录下。dataDir和dataLogDir分开到两个不同的磁盘可以大大提高ZooKeeper的性能。所以ZooKeeper的镜像文件和日志文件最好分开存放,避免日志写入影响性能
clientPort 指定监听端口
autopurge.snapRetainCount 开启自动清理日志
autopurge.purgeInterval 清理日志的时间间隔,以小时为单位
每个集合成员都有一个ID,这个ID记录到各自的dataDir目录下的myid文件,这个文件需要手动创建。
echo "1" > /tmp/zookeeper/myid
3.ZooKeeper监控
监控ZooKeeper有两种方法,一种是使用ZooKeeper自身提供的4个字母的命令查看ZooKeeper的各种状态,另外一种就是使用JMX查看
conf 查看ZooKeeper的配置信息
echo conf|nc 127.0.0.1 2181
cons 列出连接信息
echo cons|nc 172.28.2.157 2181
crst 重置连接/会话数据
echo crst|nc 172.28.2.157 2181
dump 列出比较显著的会话和节点。只能在Leader节点上使用
envi 列出环境变量
ruok 测试服务是否正常运行,如果是返回imok,否则不响应
srst 重置服务器状态
srvr 列出完整的详细信息
# echo srvr|nc 127.0.0.1 2181 Zookeeper version: 3.4.6-1569965, built on 02/20/2014 09:09 GMT Latency min/avg/max: 0/0/0 Received: 1 Sent: 1 Connections: 1 Outstanding: 0 Zxid: 0x300000025 Mode: leader Node count: 17158
stat 列出服务器的详细信息和连接到的客户端
wchs 列出watches的简洁信息
wchc 列出watches的详细信息
wchp 列出watches的详细信息,根据路径显示。这个命令可能会影响性能,慎用
mntr 列出集群的监控状况
echo mntr|nc 127.0.0.1 2181 zk_version 3.4.6-1569965, built on 02/20/2014 09:09 GMT zk_avg_latency 0 zk_max_latency 8 zk_min_latency 0 zk_packets_received 10464 zk_packets_sent 10464 zk_num_alive_connections 3 zk_outstanding_requests 0 zk_server_state leader zk_znode_count 17159 zk_watch_count 2 zk_ephemerals_count 1 zk_approximate_data_size 6666471 zk_open_file_descriptor_count 32 zk_max_file_descriptor_count 102400 zk_followers 2 zk_synced_followers 2 zk_pending_syncs 0
zk_followers,zk_synced_followers,zk_pending_syncs这几个只有leader角色才会显示
4.管理数据文件
ZooKeeper将它的数据存在数据目录下,将事务日志存在日志目录下。在默认的情况下都是存储在dataDir指定的目录下。在实际部署的时候应该将事务日志分开存放可以增加ZooKeeper服务的吞吐量和减小延迟。
# ls -lh /tmp/zookeeper/version-2/ total 20M -rw-r--r-- 1 root root 1 Feb 23 21:36 acceptedEpoch -rw-r--r-- 1 root root 1 Feb 23 21:36 currentEpoch -rw-r--r-- 1 root root 65M Feb 18 17:39 log.1 -rw-r--r-- 1 root root 65M Feb 23 20:30 log.100000001 -rw-r--r-- 1 root root 65M Feb 21 17:20 log.1cfe -rw-r--r-- 1 root root 65M Feb 25 15:33 log.300000001 -rw-r--r-- 1 root root 296 Feb 16 18:26 snapshot.0 -rw-r--r-- 1 root root 892K Feb 18 17:42 snapshot.1cfd -rw-r--r-- 1 root root 5.4M Feb 23 15:29 snapshot.807d
每个ZooKeeper服务端都有一个唯一的ID。这个ID用在两个地方,一个是myid文件,另一个是配置文件。
myid文件用来标记本地服务端的ID,在配置文件中ID用来连接其他服务器端。
snapshot.
5.需要避免的事情
在部署ZooKeeper的时候需要避免以下几个问题:
ZooKeeper主机列表不一致
每个ZooKeeper主机的配置文件中的集群主机列表应该一致,连接到ZooKeeper集群的客户端配置的主机列表页应该和ZooKeeper主机配置的列表一致
ZooKeeper的事务日志放错地方
影响ZooKeeper性能最重要的一点就是事务日志。ZooKeeper返回一个响应之前会将事务同步到磁盘上。将事务日志单独存放到一个磁盘上会大大提高ZooKeeper性能。如果将事务日志存放到一个繁忙的磁盘上明显会影响性能。
Java Heap大小设置错误
需要特别关注Java Heap大小的设置,ZooKeeper服务器不能有使用SWAP的情况发生。DON'T SWAP
保守估计的话,如果有4GB内存,那么久不能把Java的Heap大小设置成为6GB或者是4GB。最多设置成3GB左右,因为操作系统需要一些内存作为缓存。最好的就是作下压力测试。
四 ZooKeeper开发相关
想要利用ZooKeeper的协同服务来创建分布式应用的开发者需要了解以下以下的信息。
1.ZooKeeper的数据模型
ZooKeeper有一个层级域名空间
2.Znodes
ZooKeeper分层域名空间树种的每一个节点都叫做znode。
3.Watches
客户端可以在znodes上设置watches。znode有变更就会触发watch然后清理watch。当一个watch被触发,ZooKeeper会发送一个通知给客户端。ZooKeeper所有的读操作都可以设置一个watch。ZooKeeper关于watch的定义是:一个watch事件是个一次性的触发器.
参考文档
http://zookeeper.apache.org/
http://www.us.apache.org/dist/zookeeper/
http://zookeeper.apache.org/doc/r3.4.6/zookeeperOver.html
http://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html