说到分布式开发 Zookeeper 是必须了解和掌握的,分布式消息服务 kafka 、hbase 到 hadoop 等分布式大数据处理都会用到 Zookeeper,所以在此将 Zookeeper 作为基础来讲解。
Zookeeper 是分布式服务框架,主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等等。
ZooKeeper 的安装模式分为三种,分别为:单机模式、集群模式和集群伪分布模式
CentOS7.0 (windows 中使用就使用 zkServer.cmd)
ZooKeeper 最新版本
用 root 用户安装(如果用于 hbase 时将所有文件权限改为 hadoop 用户)
Java 环境,最好是最新版本的。
分布式时多机间要确保能正常通讯,关闭防火墙或让涉及到的端口通过。
去官网下载 :http://zookeeper.apache.org/releases.html#download
下载后放进 CentOS 中的 / usr/local/ 文件夹中,并解压到当前文件中 /usr/local/zookeeper(怎么解压可参考之前的 Haproxy 的安装文章)
进入 zookeeper 目录下的 conf 子目录, 重命名 zoo_sample.cfg 文件,Zookeeper 在启动时会找这个文件作为默认配置文件:
- mv /usr/local/zookeeper/conf/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/data
- dataLogDir=/usr/local/zookeeper/log
- # the port at which the clients will connect
- clientPort=2181
- #
- # 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
tickTime:毫秒值. 这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
dataLogDir:顾名思义就是 Zookeeper 保存日志文件的目录
clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
再创建上面配置的 data 和 log 文件夹:
- mkdir /usr/local/zookeeper/data
- mkdir /usr/local/zookeeper/log
先进入 / usr/local/zookeeper 文件夹
- cd /usr/local/zookeeper
再运行
- bin/zkServer.sh start
检测是否成功启动:执行
- bin/zkCli.sh
- 或
- echo stat|nc localhost 2181
所谓伪集群, 是指在单台机器中启动多个 zookeeper 进程, 并组成一个集群. 以启动 3 个 zookeeper 进程为例,模拟 3 台机。
将 zookeeper 的目录多拷贝 2 份:
zookeeper/conf/zoo.cfg 文件与单机一样,只改为下面的内容:
- tickTime=2000
- initLimit=5
- syncLimit=2
- dataDir=/usr/local/zookeeper/data
- dataLogDir=/usr/local/zookeeper/log
- clientPort=2180
- server.0=127.0.0.1:2888:3888
- server.1=127.0.0.1:2889:3889
- server.2=127.0.0.1:2890:3890
新增了几个参数, 其含义如下:
分别进入 / usr/local/zookeeper/bin, /usr/local/zookeeper1/bin, /usr/local/zookeeper2/bin 三个目录, 启动 server。启动方法与单机一致。
- bin/zkServer.sh start
分别检测是否成功启动:执行
- bin/zkCli.sh
- 或
- echo stat|nc localhost 2181
集群模式的配置和伪集群基本一致.
由于集群模式下, 各 server 部署在不同的机器上, 因此各 server 的 conf/zoo.cfg 文件可以完全一样.
下面是一个示例:
- tickTime=2000
- initLimit=5
- syncLimit=2
- dataDir=/usr/local/zookeeper/data
- dataLogDir=/usr/local/zookeeper/log
- clientPort=2180
- server.0=192.168.80.30:2888:3888
- server.1=192.168.80.31:2888:3888
- server.2=192.168.80.32:2888:3888
示例中部署了 3 台 zookeeper server, 分别部署在 192.168.80.30, 192.168.80.31, 192.168.80.32 上.
需要注意的是, 各 server 的 dataDir 目录下的 myid 文件中的数字必须不同,192.168.80.30 server 的 myid 为 0, 192.168.80.31 server 的 myid 为 1, 192.168.80.32 server 的 myid 为 2
分别进入 / usr/local/zookeeper/bin 目录, 启动 server。启动方法与单机一致。
- bin/zkServer.sh start
分别检测是否成功启动:执行
- bin/zkCli.sh
- 或
- echo stat|nc localhost 2181
这时会报大量错误?其实没什么关系,因为现在集群只起了 1 台 server,zookeeper 服务器端起来会根据 zoo.cfg 的服务器列表发起选举 leader 的请求,因为连不上其他机器而报错,那么当我们起第二个 zookeeper 实例后,leader 将会被选出,从而一致性服务开始可以使用,这是因为 3 台机器只要有 2 台可用就可以选出 leader 并且对外提供服务 (2n+1 台机器,可以容 n 台机器挂掉)。
- 1. 启动ZK服务: zkServer.sh start
- 2. 查看ZK服务状态: zkServer.sh status
- 3. 停止ZK服务: zkServer.sh stop
- 4. 重启ZK服务: zkServer.sh restart
ZooKeeper 命令行工具类似于 Linux 的 shell 环境,使用它可以对 ZooKeeper 进行访问,数据创建,数据修改等操作.
使用 zkCli.sh -server 192.168.80.31:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 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. 退出客户端: quit
- 8. 帮助命令: help
通过上述命令实践,我们可以发现,zookeeper 使用了一个类似文件系统的树结构,数据可以挂在某个节点上,可以对这个节点进行删改。另外我们还发现,当改动一个节点的时候,集群中活着的机器都会更新到一致的数据。
在简单使用了 zookeeper 之后,我们发现其数据模型有些像操作系统的文件结构,结构如下图所示
(1) 每个节点在 zookeeper 中叫做 znode, 并且其有一个唯一的路径标识,如 / SERVER2 节点的标识就为 / APP3/SERVER2
(2) Znode 可以有子 znode,并且 znode 里可以存数据,但是 EPHEMERAL 类型的节点不能有子节点
(3) Znode 中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。
(4) znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和 服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了
(5) znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为 App2
(6) znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是 zookeeper 对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
当 leader 崩溃或者 leader 失去大多数的 follower,这时候 zk 进入恢复模式,恢复模式需要重新选举出一个新的 leader,让所有的 Server 都恢复到一个正确的状态。Zk 的选举算法有两种:一种是基于 basic paxos 实现的,另外一种是基于 fast paxos 算法实现的。系统默认的选举算法为 fast paxos。
basic paxos 流程:
1 . 选举线程由当前 Server 发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的 Server;
2 . 选举线程首先向所有 Server 发起一次询问 (包括自己);
3 . 选举线程收到回复后,验证是否是自己发起的询问 (验证 zxid 是否一致),然后获取对方的 id(myid),并存储到当前询问对象列表中,最后获取对方提议的 leader 相关信息 (id,zxid),并将这些信息存储到当次选举的投票记录表中;
4. 收到所有 Server 回复以后,就计算出 zxid 最大的那个 Server,并将这个 Server 相关信息设置成下一次要投票的 Server;
5. 线程将当前 zxid 最大的 Server 设置为当前 Server 要推荐的 Leader,如果此时获胜的 Server 获得 n/2 + 1 的 Server 票数, 设置当前推荐的 leader 为获胜的 Server,将根据获胜的 Server 相关信息设置自己的状态,否则,继续这个过程,直到 leader 被选举出来。
通 过流程分析我们可以得出:要使 Leader 获得多数 Server 的支持,则 Server 总数必须是奇数 2n+1,且存活的 Server 的数目不得少于 n+1. 每个 Server 启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的 server 还会从磁盘快照中恢复数据和会话信 息,zk 会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。
是指通过指定的名字来获取资源或者服务的地址,提供者的信息。利用 Zookeeper 很容易创建一个全局的路径,而这个路径就可以作为一个名字,它可以指向集群中的集群,提供的服务的地址,远程对象等。简单来说使用 Zookeeper 做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。
阿里巴巴集团开源的分布式服务框架 Dubbo 中使用 ZooKeeper 来作为其命名服务,维护全局的服务地址列表。在 Dubbo 实现中:服务提供者在启动的时候,向 ZK 上的指定节点 / dubbo/${serviceName}/providers 目录下写入自己的 URL 地址,这个操作就完成了服务的发布。服务消费者启动的时候,订阅 / dubbo/{serviceName}/providers 目录下的提供者 URL 地址, 并向 / dubbo/{serviceName} /consumers 目录下写入自己的 URL 地址。注意,所有向 ZK 上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化。另外,Dubbo 还有针对服务粒度的监控,方法是订阅 / dubbo/{serviceName} 目录下所有提供者和消费者的信息。来源: http://www.cnblogs.com/zhangs1986/p/6564839.html