Zookeeper分布式协调服务
Apache Zookeeper旨在减轻构建健壮的分布式系统的服务。Zookeeper是基于分布式计算的核心概念而设计的,主要目的是给开发人员提供一套容易理解和开发的接口,从而简化分布式系统构建的服务。
初识Zookeeper
Zookeeper的简介
Zookeeper是一个分布式协调服务的开源框架,它是由Google的Chubby开源实现。Zookeeper主要用来解决分布式集群中应用系统的一致性问题和单点故障问题,例如如何避免同时操作同一数据造成脏读的一致性问题等。
Zookeeper的特性
Zookeeper具有全局数据一致性、可靠性、顺序性、原子性以及实时性,可以说Zookeeper的其他特性都是为满足Zookeeper全局数据一致性这一特性。
Zookeeper集群角色
Zookeeper集群是一个主从集群,它一般是由一个Leader(领导者)和多个Follower(跟随者)组成。此外,针对访问量比较大的Zookeeper集群,还可新增Observer(观察者)。Zookeeper集群中的三种角色各司其职,共同完成分布式协调服务。
- Leader
Leader是Zookeeper集群工作的核心,也是事务性请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性,同时负责进行投票的发起和决议,以及更新系统状态。 - Follower
Follower负责处理客户端的非事务(读操作)请求,如果接收到客户端发来的事务性请求,则会转发给Leader,让Leader进行处理,同时还负责在Leader选举过程中参与投票。 - Observer
Observer负责观察Zookeeper集群的最新状态的变化,并且将这些状态进行同步。对于非事务性请求可进行独立处理;对于事务性请求,则会转发给Leader服务器进行处理。它不参与任何形式的投票,只提供非事务性的服务。
数据模型
数据存储结构
Zookeeper是由节点组成的树,树中的每个节点被称为—Znode。每个节点都可以拥有子节点。每一个Znode默认能够存储1MB的数据,每个Znode都可以通过其路径唯一标识,如图中第三层的第一个Znode,,它的路径是/app1/p_1。Zookeeper数据模型中每个Znode都是由三部分组成,分别是stat、data、children。
Znode的类型
Znode的类型在创建时被指定,一旦创建就无法改变。
Znode有两种类型,分别是临时节点和永久节点。
- 临时节点
该生命周期依赖于创建它们的会话,一旦会话结束,临时节点将会被自动删除,也可以手动删除。虽然每个临时的Znode都会绑定一个客户端,但它们对所有的客户端还是可见的。需要注意的是临时节点不允许拥有子节点。 - 永久节点
该生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,它们才能被删除。
Znode的属性
Zookeeper中的每个Znode都包含了一系列的属性,具体属性如下所示。
属性名称 | 相关说明 |
---|---|
dataVersion | 数据版本号 |
aclVersion | ACL版本号 |
ephemeralOwner | 如果此节点为临时节点,那么该值代表这个节点拥有者的会话ID;否则值为0 |
dataLength | 节点数据域长度 |
numChildren | 节点拥有的子节点个数 |
dataVersion | 数据版本号 |
aclVersion | ACL版本号 |
ephemeralOwner | 如果此节点为临时节点,那么该值代表这个节点拥有者的会话ID;否则值为0 |
dataLength | 节点数据域长度 |
numChildren | 节点拥有的子节点个数 |
Zookeeper的Watcher机制
Watch机制的简介
在ZooKeeper中,引入了Watch机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watch监听,当服务端的一些事件触发了这个Watch,那么就会向指定客户端发送一个事件通知,来实现分布式的通知功能。
Watch机制的特点
- 一次性触发
- 事件封装
- 异步发送
- 先注册再触发
Watch机制的通知状态和事件类型
同一个事件类型在不同的连接状态中代表的含义有所不同。
常见的连接状态和事件类型如下所示。
连接状态 | 状态含义 | 事件类型 | 事件含义 |
---|---|---|---|
Disconnected | 连接失败 | NodeCreated | 节点被创建 |
SyncConnected | 连接成功 | NodeDataChanged | 节点数据变更 |
AuthFailed | 认证失败 | NodeChildrentChanged | 子节点数据变更 |
Expired | 会话过期 | NodeDeleted | 节点被删除 |
Zookeeper的选举机制
选举机制的简介
Zookeeper为了保证各节点的协同工作,在工作时需要一个Leader角色,而Zookeeper默认采用FastLeaderElection算法,且投票数大于半数则胜出的机制。
- 服务器ID
设置集群myid参数时,参数分别为服务器1、服务器2、服务器3,编号越大FastLeaderElection算法中权重越大。 - 选举ID
选举过程中,Zookeeper服务器有四种状态,分别为竞选状态、随从状态、观察状态、领导者状态。 - 逻辑时钟
逻辑时钟被称为投票次数,同一轮投票过程中逻辑时钟值相同,逻辑时钟起始值为0,每投一次票,数据增加。与接收到其它服务器返回的投票信息中数值比较,根据不同值做出不同判断。 - 数据ID
是服务器中存放的最新数据版本号,该值越大则说明数据越新,在选举过程中数据越新权重越大。
选举机制的类型
Zookeeper选举机制有两种类型,分别为全新集群选举和非全新集群选举。全新集群选举是新搭建起来的,没有数据ID和逻辑时钟的数据影响集群的选举;非全新集群选举时是优中选优,保证Leader是Zookeeper集群中数据最完整、最可靠的一台服务器。
全新集群选举
- 服务器1启动,先给自己投票;其次,发投票信息,由于其它机器还没有启动所以它无法接收到投票的反馈信息,因此服务器1的状态一直属于竞选状态。
- 服务器2启动,先给自己投票;其次,在集群中启动Zookeeper服务的机器发起投票对比,它会与服务器1交换结果,由于服务器2编号大,服务器2胜出,服务器1会将票投给服务器2,此时服务器2的投票数并没有大于集群半数,两个服务器状态依旧是竞选状态。
- 服务器3启动,先给自己投票;其次,与之前启动的服务器1、2交换信息,服务器3的编号最大,服务器3胜出,服务器1、2会将票投给服务器3,此时投票数正好大于半数,所以服务器3成为领导者状态,服务器1、2成为追随者状态。
- 服务器4启动,先给自己投票;其次,与之前启动的服务器1、2、3交换信息,尽管服务器4的编号大,但是服务器3已经胜,所以服务器4只能成为追随者状态。
- 服务器5启动,同服务器4一样,均成为追随者状态。
非全新集群选举
- 统计逻辑时钟是否相同,逻辑时钟小,则说明途中可能存在宕机问题,因此数据不完整,那么该选举结果被忽略,重新投票选举。
- 统一逻辑时钟后,对比数据ID值,数据ID反应数据的新旧程度,因此数据ID大的胜出。
- 如果逻辑时钟和数据ID都相同的情况下,那么比较服务器ID(编号),值大则胜出。
Zookeeper分布式集群部署
Zookeeper分布式集群部署指的是ZooKeeper分布式模式安装。Zookeeper集群搭建通常是由2n+1台服务器组成,这是为了保证 Leader 选举(基于Paxos算法的实现)能够通过半数以上台服务器选举支持,因此,ZooKeeper集群的数量一般为奇数台。
Zookeeper的Shell操作
Zookeeper Shell介绍
Zookeeper命令行工具类似于Linux的Shell环境,能够简单地实现对Zookeeper进行访问、数据创建、数据修改等的一系列操作。
常用命令 | 命令描述 |
---|---|
ls / | 使用ls命令来查看Zookeeper中所包含的内容 |
ls2 / | 查看当前节点数据并能看到更新次数等数据 |
create /zk “test” | 在当前目录创建一个新的Znode节点“zk”以及与它关联的字符串 |
get /zk | 获取zk所包含的信息 |
set /zk “zkbak” | 对zk所关联的字符串进行设置 |
delete /zk | 将节点Znode删除 |
rmr | 将节点Znode递归删除 |
help | 帮助命令 |
Zookeeper的Java API操作
Zookeeper Java API介绍
Zookeeper API包含五个包:
- org.apache.zookeeper
- org.apache.zookeeper.data
- org.apache.zookeeper.server
- org.apache.zookeeper.server.quorum
- org.apache.zookeeper.server.upgrade
org.apache.zookeeper包含Zookeeper类,这也是编程时最常用的类文件,Zookeeper类提供的常用Java API方法。
方法名称 | 方法描述 |
---|---|
create | 创建节点 |
delete | 删除节点 |
exists | 判断节点是否存在 |
get/setData | 获取/修改节点数据 |
getChildren | 获取指定节点下的所有子节点列表 |
Zookeeper典型应用场景
数据发布与订阅
数据发布与订阅模型,即所谓的全局配置中心,顾名思义就是发布者将需要全局统一管理的数据发布到Zookeeper节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,服务式服务框架的服务地址列表等就非常适合使用。
- 应用中用到的一些配置信息放到Zookeeper上进行集中管理。
- 分布式搜索服务中,索引的元信息和服务器集群机器的节点状态存放在Zookeeper的一些指定节点,供各个客户端订阅使用。
- 分布式日志收集系统中,这个系统的核心工作是收集分布在不同机器的日志。
- 系统中有些信息需要动态获取,并且还会存在人工手动去修改这个信息的发问。
统一命名服务
命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源服务的地址,提供者等信息。
分布式锁
- 分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。
- 锁服务可以分为两类,一个是保持独占,另一个是控制时序。
- 所谓保持独占,就是所有试图来获取这个锁的客户端,最终只有一个客户端可以成功获得这把锁,从而执行相应操作;控制时序则是所有试图来获取锁的客户端,最终都会被执行,存在全局时序,客户端在临时非序列化节点下创建临时序列化节点,根据序列号大小进行时序性操作。
当所有客户端都去创建临时非序列化节点,那么最终成功创建的客户端也拥有了这把锁,拥有了访问该数据的权限,当操作完毕后,断开与Zookeeper连接,那该临时节点就会被删除,如果其他客户端需要操作这个文件,客户端只需监听这个目录是否存在即可。