1、Zookeeper简介
Zookeeper是一个高可用、高性能的分布式协调服务,可用于服务发现、分布式锁、分布式领导选举、配置管理等。
这一切的基础,都是Zookeeper提供了一个类似于Linux文件系统的树形结构Znode(可认为是轻量级的内存文件系统,但只适合存少量信息,完全不适合存储大量文件或者大文件),同时提供了对于每个节点的监控与通知机制;
2、Zookeeper集群
image.png
3、Zookeeper组件
Zookeeper集群是一个基于主从复制的高可用集群,每个服务器承担如下三种角色中的一种;
-
Leader:一个Zookeeper集群同一时间只会有一个实际工作的Leader,他会发起并维护与各Follower及Observer间的心跳;所有的写操作必须要通过Leader完成,再由Leader将写操作广播给其他服务器
-
Follower:一个Zookeeper集群可能同时存在多个Follower,他会响应Leader的心跳;Follower可直接处理并返回客户端的请求,同时会将写请求转发给Leader处理,并且负责在Leader处理写请求时对请求进行投票;
-
Observer :如果Zookeeper集群的读取负载很高,或者客户端多到跨机房,可以设置一些observer服务器,以提高读取的吞吐量,Observer角色与Follower类似,但是有两个区别,一是没有投票权,即不参加选举也不响应提议,二是Observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个名字空间
image.png
4、Zookeeper特性:
Zookeeper是一个由多个server组成的集群
- 一个leader,多个follower、observer
- 每个server保存一份数据副本
- 全局数据一致
- 分布式读flower,写由leader实施
- 更新请求转发,由leader实施
- 更新请求顺序进行(FIFO),来自同一个client的更新请求按器发送顺序依次执行
- 数据更新原子性,一次数据更新要么成功,要么失败
- 全局唯一数据视图,client无论连接到哪个server,数据视图都是一致的
- 实时性,在一定时间范围内,client能读到最新数据
5、应用场景
-
分布式服务注册与订阅
在分布式环境中,为了保证高可用性,通常同一个应用或同一个服务的提供方都会部署多份,达到对等服务;而消费者就需要在这些对等的服务器中选择一个来执行相关的业务逻辑,比较典型的服务注册与订阅,消费端&消费端&生产端(负责均衡类似方案)
总结:系统之间存在某种订阅关系
适用:dubbo的provider和consumerimage.png
-
分布式配置中心
分布式配置中心,属于发布与订阅模型,顾名思义就是发布者将数据发布到ZK节点上,供订阅者获取数据,实现配置信息的集中式管理和动态更新
总结:感应变化 pull模式(C>>S)/push模式(S>>C)
适用:全局的配置信息,服务式服务框架的服务地址列表
注意点:数据量很小,但是数据更新可能会比较快的场景
代表:百度的disconf
github:https://github.com/knightliao/disconf -
命名服务
在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源、服务的地址、提供者等信息;被命名的实体通常是集群中的机器提供的服务地址、进程对象等,这些我们都可以统称他们为名字(Name)
总结:全局唯一的path、全局唯一性ID
适用:较为常见的就是一些分布式服务框架中的服务地址列表;通过调用ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称
注意:所有向ZK上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化
代表:dubbo
image.png
-
分布式通知协调
Zookeeper中特有的,watcher注册不异步通知机制,能够很好的实现分布式环境下不同系统通知与协调,实现对数据变更的实时处理;
使用方法通常是不同系统都对ZK上同一个znode节点进行注册,监听znode的变化(包括znode本身内容及子节点的),其中一个系统update了znode,那么另一个系统能够收到通知,并作出相应处理
总结:需要双系统协调做一件事情
适用:调度系统,推送系统,心跳检测等
需要两方系统一起做的事情,适用zookeeper来进行分布式通知和协调能够大大降低系统之间的耦合 -
分布式锁
分布式锁,主要是得益于zookeeper为我们保证了数据的强一致性。
6、Zookeeper写操作
- 写Leader:通过Leader进行写操作流程
1、客户端向Leader发起写请求
2、Leader将写请求以Proposal的形式发给所有Follower并等待应答(ACK)
3、Follower收到Leader的Proposal后返回ACK
4、Leader得到过半数的ACK(Leader对自己默认有一个ACK)后,向所有的Follower和Observer发送Commit
5、leader将处理结果返回客户端
image.png
这里需要注意:
1、Leader并不需要得到Observer的ACK,即Observer无投票权
2、Leader不需要得到所有Follower的ACK,只要收到过半的ACK即可,同时Leader本身对自己有一个ACK。上图中有4个Follower,只需其中两个返回ACK即可,因为 (2+1)/(4+1) > 1/2
3、Observer虽然无投票权,但仍需同步Leader的数据从而在处理读请求时可以返回尽可能新的数据
- 写Follower/Observer:通过Follower/Observer进行写操作
image.png
从上图中可以看出,Follower/Observer均可接受写请求,但不能直接处理,而需要将写请求转发给Leader处理;
除了多了异步请求转发,其他流程与直接写Leader无任何区别
7、Zookeeper读操作
image.png
Leader/Follower/Observer都可直接处理读请求,从本地内存中读取数据并返回给客户端即可;
由于处理读请求不需要服务器之间的交互,Follow/Observer越多,整体可处理的读请求量越大,也即读性能越好
8、Session会话
客户端链接zookeeper集群是通过Session链接(TCP长链接)
客户端链接以后可以对节点(存储在zookeeper上,znode)增删查改操作
9、数据模型Znode
image.png
Znode节点类型:2大类,4种类型,持久、临时、持久有序、临时有序
- PERSISTENT :持久类型,如果不手动删除,是一致存在的
- PERSISTENT_SEQUENTIAL :持久有序
- EPHEMERAL :临时类型,客户端session失效就会随着删除节点,没有子节点
- EPHEMERAL_SEQUENTIAL:临时有序,自增
Znode节点状态
image.png
image.png
10、ACL(Access Control List)
对znode节点做增删查改时我们可以监控其动作(Watcher机制),还可以对节点设置权限访问
-
内置的ACL schemes:
world:默认方式,相当于全世界都能访问
auth:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)
digest:即用户名:密码这种方式认证,这也是业务系统中最常用的
ip:使用IP地址认证 -
ACL支持权限:
CREATE:能创建子节点
READ:能获取节点数据和列出其子节点
WRITE:能设置节点数据
DELETE:能删除子节点
ADMIN:能设置权限
11、Watcher 监听
image.png
12、ZAB(原子广播)协议介绍
为了保证写操作的一致性与可用性,Zookeeper专门设计了一种名为原子广播(ZAB)的支持奔溃恢复的一致性协议,基于该协议,Zookeeper实现了一种主从模式的系统架构保持集群中各个副本之间的数据一致性;
根据ZAB协议,所有的写操作都必须通过Leader完成,Leader写入本地日志后再复制到所有的Follower节点;
一旦Leader节点无法工作,ZAB协议能够自动从Follower节点中重新选出一个合适的替代者,即新的Leader,该过程即为领导选举;该leader选举过程,是ZAB协议中最为重要和复杂的过程;
ZAB协议模式:恢复模式 广播模式
当服务启动或者在领导者崩溃后,Zab就进入了恢复密室,当领导者被选举出来,且大多数server完成了和leader的状态同步以后,恢复模式就结束。状态同步保证了leader和server具有相同的系统状态,一旦leader已经和多数的follower进行了状态同步后,leader就可以广播消息了,即进入广播模式;
这时候当一个server 加入zookeeper服务中,它会在恢复模式下起送,发现leader,并和leader进行状态同步,待到同步结束,它也会参与消息广播;
Zoopkeeper服务一直维持在Broadcast状态,直到leader奔溃了或者leader失去了大部分的followers支持。
广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证,所有的提议(proposal)都在被提出的时候加上了zxid,实现中,zxid是一个64位的数字,高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,低32位是个递增计数;
当leader奔溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的server都恢复到一个正确的状态
13、ZAB(原子广播)协议详解
在了解ZAB协议具体过程之前不要先了解几个概念。
-
事务
zookeeper作为一个分布式协调服务,需要leader节点去接受外部请求,转化为内部操作(比如创建,修改,删除节点),需要原子性执行的几个操作就组成了事务,这里用T代表。zookeeper要求有序的处理事务,因此给每个事务一个编号,每进来一个事务编号加1,假设leader节点中进来n个事务,可以表示为T1,T2,T3…Tn。为了防止单点问题导致事务数据丢失,leader节点会把事务数据同步到follower节点中。 -
事务队列
leader和follower都会保存一个事务队列,用L表示,L=T1,T2,T3…Tn,leader的事务队列是接受请求保存下来的,follower的事务队列是leader同步过来的,因此leader的事务队列是最新,最全的。 -
任期
在zookeeper的工作过程中,leader节点奔溃,重新选举出新的leader是很正常的事情,所以zookeeper的运行历史中会产生多个leader,就好比一个国家的历史中会相继出现多为领导人。为了区分各个leader,ZAB协议用一个整数来表示任期,我们假设用E表示任期。zookeeper刚运行时选举出的第一个leader的任期为E=1;第一个leader奔溃后,下面选举出来的leader,任期会加1,E=2;一次类推。加入任期概念的事务应该表示为T(E,n)
协议作用
- 选举leader
每个follower广播自己事务队列中最大事务编号maxId
获取集群中其他follower发出来的maxId,选取出最大的maxId所属的follower,投票给该follower,选它为leader。
统计所有投票,获取投票数超过一半的follower被推选为leader - 同步数据
各个follower向leader发送自己保存的任期E
leader,比较所有的任期,选取最大的E,加1后作为当前的任期E=E+1
将任务E广播给所有follower
follower将任期改为leader发过来的值,并且返回给leader事务队列L
leader从队列集合中选取任期最大的队列,如果有多个队列任期都是最大,则选取事务编号n最大的队列Lmax。将Lmax最为leader队列,并且广播给各个follower。
follower接收队列替换自己的事务队列,并且执行提交队列中的事务。
至此各个节点的数据达成一致,zookeeper恢复正常服务。 - 广播
leader节点接收到请求,将事务加入事务队列,并且将事务广播给各个follower。
follower接收事务并加入都事务队列,然后给leader发送准备提交请求。
leader 接收到半数以上的准备提交请求后,提交事务同时向follower 发送提交事务请求
follower提交事务。
14、Leader选举
LOOKING,FOLLOWING,LEADING,OBSERVING
作者:张凯_9908
链接:https://www.jianshu.com/p/00223461e5d9
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。