什么是Zookeeper
Zookeeper是开源的分布式协调服务框架,主要是来解决分布式集群中应用系统的一致性问题和数据管理问题
Zookeeper特点及架构
- 是一个分布式文件系统 适合存放小文件 也可以理解为一个数据库
zookeeper 是一个集群
zookeeper 的架构
Zookeeper 是一个基于主从架构的高可用集群
有三种角色
- Leader 一个Zookeeper 集群同一个时间只会有一个实际工作的Leader 它会发起并维护与各Follwer及Observer 间的心跳 所有的写操作必须要通过Leader 完成 再由Leader将写操作广播到其他服务器
- Follower 一个Zookeeper集群可能会同时存在多个Follower 它会响应Leader的心跳 Follower可直接处理并返回客户端的读请求 同时会把写请求转发给Leader处理 并且负责在Leader 处理写请求时对请求进行投票
- Observer 角色与Follower 相似 但是无权投票
Zookeeper的应用场景
-
数据发布和订阅
数据发布/订阅系统,需要发布者将数据发布到zookeeper的节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。发布/订阅一般有两种设计模式:推模式和拉模式,服务端主动将数据更新发送给所有订阅的客户端称为推模式;客户端主动请求获取最新数据称为拉模式.Zookeeper采用了推拉相结合的模式,客户端向服务端注册自己需要关注的节点, 一旦该节点数据发生变更,那么服务端就会向相应的客户端推送Watcher事件通知,客户端接收到此通知后,主动到服务端获取最新的数据。
可以实时获取最新的源数据
-
命名服务
命名服务是分步式系统中较为常见的一类场景,分布式系统中,被命名的实体通常可
以是集群中的机器、提供的服务地址或远程对象等,通过命名服务,客户端可以根据指定名
字来获取资源的实体,在分布式环境中,上层应用仅仅需要一个全局唯一的名字。 Zookeeper可以实现一套分布式全局唯一ID的分配机制。 通过调用Zookeeper节点创建的API接口就可以创建一个顺序节点,并且在API返回值中会返回这个节点的完整名字,利用此特性,可以生成全局ID,其步骤如下
1.客户端根据任务类型,在指定类型的任务下通过调用接口创建一个顺序节点, 如"job-”。
2.创建完成后,会返回一个完整的节点名,如"job-0000001”。
3.客户端拼接type类型和返回值后, 就可以作为全局唯一ID了, 如"type2-job-0000001"。 -
分布式协调/通知
Zookeeper中特有的Watcher注册于异步通知机制,能够很好地实现分布式环境下不同机器,甚至不同系统之间的协调与通知,从而实现对数据变更的实时处理。通常的做法是不同的客户端都对zookeeper上的同一个数据节点进行Watcher注册,监听数据节点的变化(包括节点本身和子节点),若数据节点发生变化,那么所有订阅的客户端都能够接收到相应的Watcher通知,并作出相应处理。在绝大多数分布式系统中,系统机器间的通信无外乎心跳检测、工作进度汇报和系统调度。
①心跳检测:不同机器间需要检测到彼此是否在正常运行,可以使用Zookeeper实现机
器间的心跳检测,基于其临时节点特性(临时节点的生存周期是客户端会话,客户端若宕机
后,其临时节点自然不再存在),可以让不同机器都在Zookeeper的一 个指定节点下创建临时子节点,不同的机器之间可以根据这个临时子节点来判断对应的客户端机器是否存活。通过Zookeeper可以大大减少系统耦合。 ②工作进度汇报,通常任务被分发到不同机器后,需要实时地将自己的任务执行进度汇
报给分发系统,可以在Zookeeper上选择一个节点, 每个任务客户端都在这个节点下面创建临时子节点,这样不仅可以判断机器是否存活,同时各个机器可以将自己的任务执行进度写到该临时节点中去,以便中心系统能够实时获取任务的执行进度。 ③系统调度,Zookeeper能够实现如下系统调度模式:分布式系统由控制台和一些客户
端系统两部分构成,控制台的职责就是需要将一些指令信息发送给所有的客户端,以控制他们进行相应的业务逻辑,后台管理人员在控制台上做一些操作,实际上就是修改Zookeeper上某些节点的数据,Zookeeper可以把数据变更以时间通知的形式发送给订阅客户端。 -
分布式锁
分布式锁用于控制分布式系统之间同步访问共享资源的一种方式,可以保证不同系统访
问一个或一组资源时的一致性,主要分为排它锁和共享锁。
排它锁又称为写锁或独占锁,若事务T1对数据对象O1加上了排它锁,那么在整个加锁期间,只允许事务T1对O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作,直到T1释放了排它锁 ①获取锁,在需要获取排它锁时,所有客户端通过调用接口,在/exclusive_ lock节点下创建临时子节点/exclusive_lock/lock。 Zookeeper可以保证只有一个客户端能够创建成功,没有成功的客户端需要注册/exclusive_ lock节点监听。
②释放锁,当获取锁的客户端宕机或者正常完成业务逻辑都会导致临时节点的删除,此
时,所有在/exclusive_ lock节点上注册监听的客户端都会收到通知,可以重新发起分布式锁获取。 共享锁又称为读锁,若事务T1对数据对象O1加上共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁,直到该数据对象上的所有共享锁都被释放。在需要获取共享锁时,所有客户端都会到/shared _lock 下面创建一个临时顺序节点。
-
分布式队列
有一些时候,多个团队需要共同完成一个任务, 比如,A团队将Hadoop集群计算的结果交给B团队继续计算,B完成了自己任务再交给C团队继续做。这就有点像业务系统的工作流一样,一环一环地传下去分布式环境下,我们同样需要一个类似单进程队列的组件,用来实现跨进程、跨主机、跨网络的数据共享和数据传递,这就是我们的分布式队列。
Zookeeper 选举机制
Leader选举是保证分布式数据一致性的关键。当zookeeper集群中的一台数据出现以下两种情况的时候,需要进行leader选举。
-
服务器启动时选举Leader
若进行Leader选举,则至少需要两台机器,这里选取3台机器组成的服务器集群为例。在
集群初始化阶段,当有一台服务器Server1启动时, 其单独无法进行和完成Leader选举,当第
二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是
进入Leader选举过程。选举过程如下
**(1)每个Server发出一个投票。**由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0), Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
**(2)接受来自各个服务器的投票。**集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
**(3处理投票)。**针对每一个投票, 服务器都需要将别人的投票和自己的投票进行PK, PK规则如下: 优先检查ZXID。ZXID比较大的服务器优先作为Leader.
如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。
对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0,再比较myid,此时Server2的myid最大, 于是更新自己的投票为(2, 0),然后重新投票,对于Server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
**(4)统计投票.**每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、 Server2而言, 都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader.
**(5)改变服务器状态。**一旦确定了Leader,每个服务器就会更新自己的状态,如果是
Follower,那么就变更为FOLLOWING,如果是Leader, 就变更为LEADING. -
服务器运行时选举leader
在Zookeeper运行期间,Leader与非Leader服务器各司其职, 即便当有非Leader服务器宕机或新加入,此时也不会影响Leader,但是一旦Leader服务器挂了 ,那么整个集群将暂停对外服务,进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致过程相同。
Zookeeper的安装
第一步: 下载安装包
https://www.apache.org/dist/zookeeper
上传至服务器 解压
在官网上有两个tar.gz文件,从目前的最新版本3.5.5开始,带有bin名称的包才是我们想要的下载可以直接使用的里面有编译后的二进制的包,而之前的普通的tar.gz的包里面是只是源码的包无法直接使用
修改配置文件
第一台机器修改配置文件
cd /tools/apache-zookeeper-3.6.2-bin/conf
cp zoo_sample.cfg zoo.cfg
mkdir -p /tools/apache-zookeeper-3.6.2-bin/zkdatas/ #创建一个放数据的文件夹 mkdir -p :递归创建目录,即使上级目录不存在,会按目录层级自动创建目录
#修改操作系统的/etc/hosts文件,添加IP与主机名映射:
# zookeeper cluster servers
vim /ets/hosts
192.168.92.128 node01
192.168.92.130 node02
192.168.92.131 node03
vim zoo.cfg #对参数进行设置
dataDir = /tools/apache-zookeeper-3.6.2-bin/zkdatas/
#保留多少个快照
autopurge.snapRetainCount=3
#日志多少小时清理一次
autopurge.purgeInterval=1
#服务器集群地址
server.1=node01:2881:3881
server.2=node02:2882:3882
server.3=node03:2883:3883
添加myid配置
在第一台机器的/tools/zookeeper-3.6.2/zkdatas/ 路径下创建一个文件 文件名为myid,文件内容为1
mkdir /tools/apache-zookeeper-3.6.2-bin/zkdatas
touch /tools/apache-zookeeper-3.6.2-bin/zkdatas/myid
echo 1 > /tools/apache-zookeeper-3.6.2-bin/zkdatas/myid #或者vim修改
安装包分发 并修改myid的值
第一台机器
scp -r /tools/apache-zookeeper-3.6.2-bin/ node02:/tools/
scp -r /tools/apache-zookeeper-3.6.2-bin/ node03:/tools/
然后分别进入这两台服务器
修改myid
三台机器启动zookeeper服务
在安装目录的/bin目录下有zkServer.sh
cd /tools/apache-zookeeper-3.6.2/bin/
./zkServer.sh start
查看启动状态
./zkServer.sh status
使用 jps 命令
看到有QuorumPeerMain 就是启动成功了
然后启动第二台 第三台
这样启动的话 第二台就是Leader了
因为 过半选举 第二台的myid比第一台的高 所以第二台就成为了Leader 第三台因为已经选出Leader 就不用选举了