本系列文章内容大部分总结自倪超老师的《从Paxos到Zookeeper分布式一致性原理与实践》,如果想了解zookeeper,那么读着一本书就够了。链接如下:
本文先介绍下什么是zookeeper。
zookeeper介绍
zookeeper是一个开发源码的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。其设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
zookeeper致力于提供一个高性能、高可用,且具有严格的顺序访问控制能力(主要是写操作的严格顺序性)的分布式协调服务。
zookeeper使得分布式程序能够通过一个共享的、树型结构的名字空间来进行相互协调。这里zode树形结构的名字空间,是指zookeeper服务器内存中的一个数据模型,由一系列被称为znode的数据节点组成,而znode之间的层级关系就像文件系统的目录结构一样。不过zookeeper将全量数据存储在内存中,以此来实现提高服务器吞吐、减少延迟的目的。
说白了,zookeeper就是通过内部维护的znode树状模型,来协助分布式应用完成一些分布式协调工作。常见的应用场景有:数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、master选举、分布式锁和分布式队列等。(详见此文)
zookeeper特性
1.顺序性
从同一个客户端发送的请求,最终将会严格按照其发送顺序进入zookeeper中,先进先出。
2.原子性
所有请求的响应结果咋整个分布式集群环境中具有原子性。要么都成功地处理了该请求,要么都没处理。
3.单一性
无论客户端连接到哪个zookeeper服务器,所看到的服务端数据模型都是一致的,不会出现两种数据状态。(zookeeper之间是有同步机制的)
4.可靠性
一旦服务器数据状态发生了变化,就会立即存储起来。
5.实时性
当某个请求成功处理后,客户端能够立即获取服务端的最新数据状态,整个过程具有实时性。
zoo.config配置文件
参考样例:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
clientPort=2181
server.<id>=<ip>:<port1>:<port2>
server.<id>=<ip>:<port1>:<port2>
-- port1:leader节点和follow节点进行心跳检测与数据同步所用的端口
-- port2:领导选举中,用于投票通信的接口
tickTime: 称为"喃塔时间",用于配置ZooKeeper中最小时间单元的长度,实际上 ZooKeeper 中很多运行时的时间间隔都是使用 tickle 的倍数来表示的。例如, ZooKeeper 中会话的最小超时时间默认为2倍的 tickTime, 即 2*tickTime。 该配置项的默认值为3000, 单位为毫秒。
initLimit: 用于配置Leader节点等待Follower节点启动并完成数据同步的时间。 Follower节点在启动过程中会与Leader节点建立连接并完成对数据的同步,从而确定自己对外提供服务的起始状态,Leader节点允许Follower节点在initLimit时间内完成这个工作。该配置项的默认值为 10, 即10*tickTime。 通常情况下,我们不用太在意这个配置项,使用其默认值即可。如果随着ZooKeeper集群管理的数据量不断增大,Follower节点在启动的时候,从Leader节点上进行数据同步的时间也会相应变长,于是无法在较短的时间内完成数据同步,在这种情况下,有必要适当调大这个参数。
syncLimit:用于配置Leader节点和Follower节点之间进行"心跳检测"的最大延时时间。在ZooKeeper集群运行过程中,Leader节点会与所有Follower节点进行心跳检测来确定该节点是否存活。如果 Leader节点在 syncLimit 时间内无法获取Follower节点的心跳检测响应,那么Leader节点就会认为该Follower节点己经脱离了与自己的同步。该配置的默认值为5, 即5*tickTime。
dataDir: 用于配置ZooKeeper服务器存储快照文件的目录,不建议将其指定到/tmp目录下,因为该目录下的文件可能被自动删除。在ZooKeeper集群环境中,将生成一个名为myid的文件,该文件用于存放ZooKeeper集群节点的ID, 我们需保证在整个集群环境中,这个ID是唯一的。
clientPort:用于配置当前ZooKeeper服务器对外暴露的端口,客户端会通过该端口在 ZooKeeper服务器上建立连接并创建会话,一般设置为2181。每台ZooKeeper服务器都可以配置任意可用的端口, 实际上,集群中的所有服务器也无须使用相同的clientPort。