顾名思义 zookeeper 就是动物园管理员,他是用来管 hadoop(大象)、Hive(蜜蜂)、pig(小 猪)的管理员, Apache Hbase 和 Apache Solr 的分布式集群都用到了 zookeeper;Zookeeper: 是一个分布式的、开源的程序协调服务,是 hadoop 项目下的一个子项目。他提供的主要功 能包括:配置管理、名称服务、分布式锁、集群管理。node
功能特性
- 最终一致性:client 不论链接到哪一个 Server,展现给它都是同一个视图,这是 zookeeper 最重要的性能。
- 可靠性:具备简单、健壮、良好的性能,若是消息 m 被到一台服务器接受,那么它 将被全部的服务器接受。
- 实时性:Zookeeper 保证客户端将在一个时间间隔范围内得到服务器的更新信息,或 者服务器失效的信息。但因为网络延时等缘由,Zookeeper 不能保证两个客户端能同时获得 刚更新的数据,若是须要最新数据,应该在读数据以前调用 sync()接口。
- 等待无关(wait-free):慢的或者失效的 client 不得干预快速的 client 的请求,使得每 个 client 都能有效的等待。
- 原子性:更新只能成功或者失败,没有中间状态。
顺序性:包括全局有序和偏序两种:全局有序是指若是在一台服务器上消息 a 在消息 b 前发布,则在全部 Server 上消息 a 都将在消息 b 前被发布;偏序是指若是一个消息 b 在消 息 a 后被同一个发送者发布,a 必将排在 b 前面。算法
进程角色
- 集群的两种模式
- 恢复模式:集群的一种非稳定状态,集群不能处理外部请求;集群启动或遇到leader崩溃时,集群进入恢复模式,在本模式中选举leader,leader选举完成后其余节点与leader进行数据同步,当过半节点完成同步后恢复模式结束,进入广播模式。
- 广播模式:集群的稳定状态,集群能正常的处理外部请求;此时如有新节点加入,新节点会自动从leader同步数据。
- 集群启动过程:
- leader选举原则
- 集群中只有超过半数的节点处于正常状态,集群才能稳定,才能处理外部请求。
- 集群正常工做以前myid小的节点会优先给myid大的节点投票,直到选出leader为止。
- 选出leader以前,集群全部节点都处于looking状态,选举成功后,除leader节点外,其他节点的状态由looking变为following,角色也成为了follower。
- leader选举过程
- 假设集群有5个节点,myid分别为1~5,假设集群第一次启动,全部节点都没有历史数据,启动顺序1~5。由集群节点数量可知,至少要有3个节点正常,集群才能稳定工做。
- 节点1启动,其初始状态为looking,发起一轮选举,节点1投本身一票,因为不过半,本轮选举没法完成。节点1仍然保持looking状态。
- 节点2启动,其初始状态为looking,它也发起一轮选举,节点2投本身一票;节点1也参与进本轮投票,打算给本身投一票,可是发现节点2的myid比本身的大,就改投节点2一票;本轮投票事后节点1得0票,节点2得2票,因为节点2的得票数不过半,因此本轮选举未能完成;节点一、2都保持looking状态。
- 节点3启动,其初始状态为looking,它也发起一轮选举,且节点3先投本身一票;节点一、2也都参与进本轮投票中来,打算投本身一票,发现本轮中节点3的myid大于本身的,因此节点一、2都转投节点3一票;此时节点3就收获了3票,超过了集群节点的半数,节点3率先当选,并从looking状态变为leading状态。节点一、2的状态变为following。
- 节点4启动,其初始状态为looking,它也发起一轮选举;此时因为节点一、2处于following状态,这两个节点就不参与本轮选举。节点4本打算投本身一票,可是发现节点3已进入leading状态,且票数已通过半,此时节点4就会将本身的一票转投给节点3。节点4未收到投票,状态由looking变为following。
- 节点5的启动过程与节点4同样,最终未得到投票,也处于following状态。
- 最终节点3成为leader,节点一、二、四、5成为follower。
- 崩溃恢复过程:当leader崩溃后,集群中的其余follower节点会从新变为looking状态,从新进行leader选举。选举过程同启动时的leader选举同样。
- 消息广播算法:
- Znode
在 Zookeeper 中,znode 是一个跟 Unix 文件系统路径类似的节点,能够往这个节点存储 或获取数据。 Zookeeper 底层是一套数据结构。这个存储结构是一个树形结构,其上的每个节点, 咱们称之为“znode” zookeeper 中的数据是按照“树”结构进行存储的。并且 znode 节点还分为 4 中不一样的类 型。 每个 znode 默认可以存储 1MB 的数据(对于记录状态性质的数据来讲,够了) 可使用 zkCli 命令,登陆到 zookeeper 上,并经过 ls、create、delete、get、set 等命令 操做这些 znode 节点
- Znode 节点类型
- bin:放置运行脚本和工具脚本,若是是 Linux 环境还会有有 zookeeper 的运 行日志 zookeeper.out
- conf:zookeeper 默认读取配置的目录,里面会有默认的配置文件
- contrib:zookeeper 的拓展功能
- dist-maven:zookeeper的 maven 打包目录
- docs:zookeeper 相关的文档
- lib:zookeeper 核心的 jar
- recipes:zookeeper 分布式相关的 jar 包
src:zookeeper 源码缓存
单机部署
Zookeeper 在启动时默认的去 conf 目录下查找一个名称为 zoo.cfg 的配置文件。 在 zookeeper 应用目录中有子目录 conf。其中有配置文件模板,手动拷贝重命名:zoo_sample.cfg cp zoo_sample.cfg zoo.cfg。zookeeper 应用中的配置文件为 conf/zoo.cfg。 修改配置文件 zoo.cfg - 设置数据缓存路径
安装jdk,配置相关环境变量,上传zookeeper压缩包
[zk_hom]# tar -zxvf apache-zookeeper-3.5.5-bin.tar.gz //解压
[zk_hom]# mkdir zkdata //新建一个数据持久化目录
[zk_hom]# cd conf //进入配置目录
[zk_hom/confg]# cp zoo_example.cfg zoo.cfg //复制配置文件样本,并重命名未zoo.cfg
编解zoo.cfg,将其中的dataDir = zk_home/zkdata
[zk_hom/bin]# sh ./zkServer.sh start //启动节点
[zk_hom/bin]# sh ./zkServer.sh status //查看节点状态服务器
集群部署
- 各个节点上的准备工做同单机的同样,都须要jdk,zookeeper压缩包,同时要拷贝配置并配置数据持久化目录,同时为各节点新建持久化目录。
- 不一样的是须要在各节点的zookeeper持久化目录中新建一个名为“myid”的文件,文件中各自写上节点编号1~5。
- 配置文件中须要追加集群中其余节点的访问地址:
【server.myid = ip:通讯端口:选举端口】
server.1 = 192.168.50.1:2181:3181
server.2 = 192.168.50.2:2181:3181
server.3 = 192.168.50.3:2181:3181
server.4 = 192.168.50.4:2181:3181
server.5 = 192.168.50.5:2181:3181
启动各个节点网络
应用管理
bin/zkServer.sh start //开启服务
bin/zkServer.sh status //查看服务状态
bin/zkServer.sh stop //中止服务端
bin/zkCli.sh -server 192.168.199.175:2181 //使用客户端链接服务端数据结构
客户端命令
应用场景
- 配置管理
在咱们的应用中除了代码外,还有一些就是各类配置。好比数据库链接等。通常咱们都 是使用配置文件的方式,在代码中引入这些配置文件。当咱们只有一种配置,只有一台服务 器,而且不常常修改的时候,使用配置文件是一个很好的作法,可是若是咱们配置很是多, 有不少服务器都须要这个配置,这时使用配置文件就不是个好主意了。这个时候每每须要寻 找一种集中管理配置的方法,咱们在这个集中的地方修改了配置,全部对这个配置感兴趣的 均可以得到变动。Zookeeper 就是这种服务,它使用 Zab 这种一致性协议来提供一致性。现 在有不少开源项目使用 Zookeeper 来维护配置,好比在 HBase 中,客户端就是链接一个 Zookeeper,得到必要的 HBase 集群的配置信息,而后才能够进一步操做。还有在开源的消 息队列 Kafka 中,也使用 Zookeeper来维护broker的信息。在 Alibaba开源的 SOA 框架Dubbo 中也普遍的使用 Zookeeper 管理一些配置来实现服务治理。
- 名称服务
名称服务这个就很好理解了。好比为了经过网络访问一个系统,咱们得知道对方的 IP 地址,可是 IP 地址对人很是不友好,这个时候咱们就须要使用域名来访问。可是计算机是 不能是域名的。怎么办呢?若是咱们每台机器里都备有一份域名到 IP 地址的映射,这个倒 是能解决一部分问题,可是若是域名对应的 IP 发生变化了又该怎么办呢?因而咱们有了 DNS 这个东西。咱们只须要访问一个你们熟知的(known)的点,它就会告诉你这个域名对应 的 IP 是什么。在咱们的应用中也会存在不少这类问题,特别是在咱们的服务特别多的时候, 若是咱们在本地保存服务的地址的时候将很是不方便,可是若是咱们只须要访问一个你们都 熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
- 分布式锁
其实在第一篇文章中已经介绍了 Zookeeper 是一个分布式协调服务。这样咱们就能够利 用 Zookeeper 来协调多个分布式进程之间的活动。好比在一个分布式环境中,为了提升可靠 性,咱们的集群的每台服务器上都部署着一样的服务。可是,一件事情若是集群中的每一个服 务器都进行的话,那相互之间就要协调,编程起来将很是复杂。而若是咱们只让一个服务进 行操做,那又存在单点。一般还有一种作法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,当即 fail over 到另外的服务。这在不少分布式系统 中都是这么作,这种设计有一个更好听的名字叫 Leader Election(leader 选举)。好比 HBase 的 Master 就是采用这种机制。但要注意的是分布式锁跟同一个进程的锁仍是有区别的,所 以使用的时候要比同一个进程里的锁更谨慎的使用。
- 集群管理
在分布式的集群中,常常会因为各类缘由,好比硬件故障,软件故障,网络问题,有些 节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其余机 器须要感知到这种变化,而后根据这种变化作出对应的决策。好比咱们是一个分布式存储系 统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候咱们要根据如今集群目 前的状态来分配存储节点。这个时候咱们就须要动态感知到集群目前的状态。还有,好比一 个分布式的 SOA 架构中,服务是一个集群提供的,当消费者访问某个服务时,就须要采用 某种机制发现如今有哪些节点能够提供该服务(这也称之为服务发现,好比 Alibaba 开源的 SOA 框架 Dubbo 就采用了 Zookeeper 做为服务发现的底层机制)。还有开源的 Kafka 队列就 采用了 Zookeeper 做为 Cosnumer 的上下线管理。
- 负载均衡的集群管理