Zookeeper
- 基于zk集群实现分布式配置中心
1. Zookeeper 是什么?
简单来说zookeeper=文件系统 + 监听通知机制。
1.1 文件系统
文件系统就是一个节点树,最头上的是根,
再往下就有各级目录,每个目录中或者是文件或者是下一级的目录
每个子目录项如 NameService 都被称作为 znode(目录节点),
和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,
唯一的不同在于znode是可以存储数据的
需要额外注意以下几点:
znode 中的数据可以有多个版本,在查询该 znode 数据时就需要带上版本信息。(set path version / delete path version)
znode 可以是临时 znode(create -e 生成的节点),一旦创建这个 znode 的 client 与server 断开连接,该znode 将被自动删除。client 和 server 之间通过 heartbeat 来确认连接正常,这种状态称之为 session,断开连接后 session 失效。
临时 znode 不能有子 znode。
znode 可以自动编号(create -s 生成的节点),例如在 create -s /app/node 已存在时,将会生成/app/node00***001 节点。
znode 可以被监控,该目录下某些信息的修改,例如节点数据、子节点变化等,可以主动通知监控注册的 client。事实上,通过这个特性,可以完成许多重要应用,例如配置管理、信息同步、分布式锁等等。
1.2 监听通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
zookeeper功能非常强大,可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理等功能,
我们这里拿比较简单的分布式应用配置管理为例来说明。
假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,
需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,
保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,
一旦配置信息发生变化,每个应用程序就会收到 zookeeper 的通知,然后从 zookeeper 获取新的配置信息应用到系统中。
每个ZNode上可存储少量数据(默认是1M, 可以通过配置修改, 通常不建议在ZNode上存储大量的数据)
配置文件文件大的话,个人建议不要用Zookeeper作为配置中心
1.3 概念
先来看看官网的解释:
关键信息:ZooKeeper是用于维护配置信息,命名,提供分布式同步以及提供组服务的集中式服务。
配置管理
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。但是当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,而且还可能是动态的话使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。比如我们可以把配置放在数据库里,然后所有需要配置的服务都去这个数据库读取配置。但是,因为很多服务的正常运行都非常依赖这个配置,所以需要这个集中提供配置服务的服务具备很高的可靠性。一般我们可以用一个集群来提供这个配置服务,但是用集群提升可靠性,那如何保证配置在集群中的一致性呢? 这个时候就需要使用一种实现了一致性协议的服务了。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的上下线管理。
更详细的描述参考此文章:https://www.yuque.com/realskrman/bi4s0n/ho3b8b
1.4 服务注册中心
Zookeeper是可以作为服务注册中心的,经常和Dubbo来整合使用。
除了Zookeeper,还有其他的注册中心:
- eureka:SpringCLoud项目产品
- nacos:阿里产品,springcloud-alibaba集成
- consul:HashiCorp 公司推出的开源工具
- 等..
2. 安装
2.1 单机测试
2.1.1 WIndow环境
其实很简单,参考我的这个文章:Dubbo + Zookeeper
2.1.2 Linux环境
1、下载 首先我们下载稳定版本的zookeeper http://zookeeper.apache.org/releases.html
2、上传 下载完成后,将zookee er压缩包zookeeper-3.4.14.tar.gz
上传到linux系统
3、解压缩压缩包
1 | tar -zxvf zookeeper-3.4.14.tar.gz |
4、进入zookeeper-3.4.14
目录,创建data文件夹
1 | cd zookeeper-3.4.14 mkdir data |
5、修改配置文件名称(因为Zookeeper默认读取的是 zoo.cfg
文件)
1 | cd conf |
5、修改zoo.cfg
中的data属性
1 | dataDir=/root/zookeeper-3.4.14/data |
6、zookeeper服务启动 进入bin目录,输入命令启动服务
1 | ./zkServer.sh start |
输出以下内容表示启动成功
关闭服务输入命令
1 | ./zkServer.sh stop |
输出以下提示信息
查看状态
1 | ./zkServer.sh status |
如果启动状态,提示:
如果未启动状态,提示:
2.2 伪集群模式
这里介绍Linux搭建(WIndos也可以,步骤类似)
首先来说并不太复杂,和我的Redis的伪集群搭建类似
大致步骤:1.复制修改三份配置文件,2. 启动三份服务
Zookeeper不但可以在单机上运行单机模式,Zookeeper,而且可以在单机模拟集群模式Zookee per的运行,也就是将不同实例运行在同一台机器,用端口进行区分,伪集群模式为我们体验Zookeeper和做一 些尝试性的实验提供了很大的便利。比如,我们在测试的时候,可以先使用少量数据在伪集群模式下进行测试。当测试可行的时候,再将数据移植到集群模式进行真实的数据实验。这样不但保证了它的可行 性,同时大大提高了实验的效率。这种搭建方式,比较简便,成本比较低,适合测试和学习
注意事项 :
—台机器上部署了 3个server,也就是说单台机器及上运行多个Zookeeper实例。这种情况下,必须保 证每个配置文档的各个端口号不能冲突,除client Port不同之外,dataDir也不同。另外,还要在 dataDir所对应的目录中创建myid文件来指定对应的Zookee per服务器实例
■ client Port 端口:
如果在1台机器上部署多个server,那么每台机器都要不同的client Port,比如serverl是2181,server2 是2182, server3是2183
■ dataDir 和 dataLogDir:
dataDi r和dataLogDir也需要区分下,将数据文件和日志文件分开存放,同时每个server的这两变量所 对应的路径都是不同的
■ server.X 和 yid:
server.X这个数字就是对应,data/myid中的数字。在3个server的myid文件中分别写入了1, 2, 3,那 么每个serve r中的zoo.cfg都配server.1 server.2,server.3就行了。因为在同一台机器上,后面连着的2 个端口,3个server都不要一样,否则端口冲突
下载
首先我们下载最新稳定版本的 zookee per htt p://zookee per.a pache.org/releases.html 上传 下载完成后,将zookee per压缩包zookee per-3.4.14.tar.gz上传到linux系统 解压压缩包 创建目录zkcluster
1 | mkdir zkcluster |
解压zookee per-3・4・14・tar・gz到zkcluster目录下
1 | tar -zxvf zookeeper-3.4.14.tar.gz -C /zkcluster |
改变名称
1 | mv zookeeper-3.4.14 zookeeper01 |
复制并改名
1 | cp -r zookeeper01/ zookeeper02 cp -r zookeeper01/ zookeeper03 |
分别在zookeeper01、zookeeper02、zookeeper03目录下创建data及logs目录
1 | mkdir data |
修改配置文件名称
1 | cd conf |
配置每一个 Zookee per 的 dataDir (zoo.cfg) client Port 分别为2181 2182 2183
1 | clientPort=2181 |
配置集群
⑴ 在每个zookeeper的data目录下创建一个myid文件,内容分别是1、2、3。这个文件就是记录 每个服务器的ID
1 | touch myid |
(2) 在每一个zookeeper的zoo.cfg配置客户端访问端口(clientPort)和集群服务器IP列表。
1 | server.1=10.211.55.4:2881:3881 |
# server.服务器ID=服务器IP地址:服务器之间通信端口:服务器之间投票选举端口
启动集群 依次启动三个zk实例
节点状态查看
1 | node1 |
2.3 真集群模式
也就是相当于类似上面伪集群的操作。不过不是在一旦机器上配置三份。而是在三台服务器上配置三份。
3. 配置文件
上面的配置基本都是在 zoo.cfg
,这里来解释一下配置文件的作用
1 | # cp conf/zoo_sample.cfg conf/zoo.cfg |
4. 系统模型
ZooKee per 数据模型 Znode 在ZooKeeper中,数据信息被保存在一个个数据节点上,这些节点被称为znode。ZNode是Zookee per中最小数据单位,在ZNode下面又可以再挂ZNode,这样一层层下去就形成了一个层次化 命名空间ZNode树,我们称为ZNode Tree,它采用了类似文件系统的层级树状结构进行管理。见下图 示例:
在Zookeeper中,每一个数据节点都是一个ZNode,上图根目录下有两个节点,分别是;app1和 app2,其中app1下面又有三个子节点,所有ZNode按层次化进行组织,形成这么一颗树,ZNode的节 点路径标识方式和Unix文件系统路径非常相似,都是由一系列使用斜杠(/)进行分割的路径表示,开 发人员可以向这个节点写入数据,也可以在这个节点下面创建子节点。
4.1 ZNode类型
刚刚已经了解到,Zookeeper的znode tree是由一系列数据节点组成的,那接下来,我们就对数据节点 做详细讲解
Zookee per节点类型可以分为三大类:
- 持久性节点(Persistent)
- 临时性节点(Ephemeral)
- 顺序性节点(Sequential))
在开发中在创建节点的时候通过组合可以生成以下四种节点类型:持久节点、持久顺序节点、临时节 点、临时顺序节点。不同类型的节点则会有不同的生命周期
持久节点:
是Zookeeper中最常见的一种节点类型,所谓持久节点,就是指节点被创建后会一直存在服 务器,直到删除操作主动清除
持久顺序节点:
就是有顺序的持久节点,节点特性和持久节点是一样的,只是额外特性表现在顺序上。 顺序特性实质是在创建节点的时候,会在节点名后面加上一个数字后缀,来表示其顺序。
临时节点:
就是会被自动清理掉的节点,它的生命周期和客户端会话绑在一起,客户端会话结束,节点会被删除掉。与持久性节点不同的是,临时节点不能创建子节点。
临时顺序节点
就是有顺序的临时节点,和持久顺序节点相同,在其创建的时候会在名字后面加上数字 后缀。
事务ID
首先,先了解,事务是对物理和抽象的应用状态上的操作集合。往往在现在的概念中,狭义上的事务通 常指的是数据库事务,一般包含了一系列对数据库有序的读写操作,这些数据库事务具有所谓的ACID特 性,即原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
而在ZooKeeper中,事务是指能够改变ZooKeeper服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新等操作。对于每一个事务请求,ZooKeeper都会 为其分配一个全局唯一的事务ID,用 **ZXID **来表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些ZXID中可以间接地识别出ZooKeeper处理这些更新操作请求的全局顺序
4.2 ZNode的状态信息
我先来写几个命令
1 | #根目录的所有节点 |
整个ZNode节点内容包括两部分:节点数据内容和节点状态信息。那么这些状态信息都有什么含义呢?
- cZxid Create ZXID:表示节点被创建时的事务ID
- ctime Create Time:表示节点创建时间。
- mZxid Modified ZXID:表示节点最后一次被修改时的事务ID。
- mtime Modified Time:表示节点最后一次被修改的时间。
- pZxid:表示该节点的子节点列表最后一次被修改时的事务ID。只有子节点列表变更才会更新pZxid,子节点内容变更不会更新。
- eversion:表示子节点的版本号。
- dataVersion: 表不内容版本号。
- aclVersion: 标识 acl 版本
- ephemeralOwner:表示创建该临时节点时的会话sessionID,如果是持久性节点那么值为0 dataLength表示数据长度。
- numchildren:表示直系子节点数。
4.3 Watcher
Watcher 数据变更通知
Zookeeper使用Watcher机制实现分布式数据的发布/订阅功能 —个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题 对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。
在ZooKeeper中,引入了 Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务 端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watche r,那么就会向指定客户端发 送一个事件通知来实现分布式的通知功能。
整个Watcher注册与通知过程如图所示。
Zookeeper的Watcher机制主要包括客户端线程、客户端WatcherManager、Zookeeper服务器三部 分。
具体工作流程为:客户端在向Zookee per服务器注册的同时,会将Watcher对象存储在客户端的 WatcherManager当中。当Zookeeper服务器触发Watcher事件后,会向客户端发送通知,客户端线程 从WatcherManager中取出对应的Watcher对象来执行回调逻辑。
这种监听机制,把压力分散在了每一个服务器上,去监听这个zookeeper中心。监听数据变化
4.4 ACL
ACL–保障数据的安全
Zookee per作为一个分布式协调框架,其内部存储了分布式系统运行时状态的元数据,这些元数据会直 接影响基于Zookee per进行构造的分布式系统的运行状态,因此,如何保障系统中数据的安全,从而避 免因误操作所带来的数据随意变更而导致的数据库异常十分重要,在Zookee per中,提供了一套完善的 ACL (Access Control List)权限控制机制来保障数据的安全。
我们可以从三个方面来理解ACL机制:**权限模式(Scheme)、授权对象(ID)、权限 (Permission),通常使用scheme: id : permission
**来标识一个有效的ACL信息。
权限模式:Scheme
权限模式用来确定权限验证过程中使用的检验策略,有如下四种模式:
ip
IP模式就是通过IP地址粒度来进行权限控制,如”i p:192.168.0.110”表示权限控制针对该IP地址, 同时IP模式可以支持按照网段方式进行配置,如”ip :192.168.0.1/24”表示针对192.168.0.*这个网段 进行权限控制。
Digest
Digest是最常用的权限控制模式,要更符合我们对权限控制的认识,其使
用”username: password”形式的权限标识来进行权限配置,便于区分不同应用来进行权限控制。
当我们通过”username:password”形式配置了权限标识后,Zookeeper会先后对其进行SHA-1加密 和BASE64编码。
World
World是一种最开放的权限控制模式,这种权限控制方式几乎没有任何作用,数据节点的访问权限 对所有用户开放,即所有用户都可以在不进行任何权限校验的情况下操作ZooKee per上的数据。 另外,World模式也可以看作是一种特殊的Digest模式,它只有一个权限标识,即”world: anyone”。
Super
Super模式,顾名思义就是超级用户的意思,也是一种特殊的Digest模式。在Super模式下,超级 用户可以对任意ZooKee per上的数据节点进行任何操作。
授权对象:ID
授权对象指的是权限赋予的用户或一个指定实体,例如IP地址或是机器等。在不同的权限模式下,授 权对象是不同的,表中列出了各个权限模式和授权对象之间的对应关系。
权限
权限就是指那些通过权限检查后可以被允许执行的操作。在ZooKee per中,所有对数据的操作权限分为 以下五大类:
CREATE (C):数据节点的创建权限,允许授权对象在该数据节点下创建子节点。
DELETE (D): 子节点的删除权限,允许授权对象删除该数据节点的子节点。
READ (R):数据节点的读取权限,允 许授权对象访问该数据节点并读取其数据内容或子节点列表等。
WRITE (W):数据节点的更新权 限,允许授权对象对该数据节点进行更新操作。
ADMIN (A):数据节点的管理权限,允许授权对象 对该数据节点进行ACL相关的设置操作。
5. 命令
现在已经搭建起了一个能够正常运行的zookee per服务了,所以接下来,就是来借助客户端来对 zookee per的数据节点进行操作 首先,进入到zookee per的bin目录之后 通过zkClient进入zookee per客户端命令行
./zkcli.sh 连接本地的zookee per服务器
./zkCli.sh -server ip:p ort连接指定的服务器
连接成功之后,系统会输出Zookee per的相关环境及配置信息等信息。输入hel p之后,屏幕会输出可用 的Zookeeper命令,如下图所示
1、创建节点
使用Create命令,可以•创建一个Zookee per节点,如
1 | create [-s][-e] path data acl |
其中,-s或-e分别指定节点特性,顺序或临时节点,若不指定,则创建持久节点;acl用来进行权限控制。
2、创建顺序节点
1 | create -s /zk-test 123 |
执行完后,就在根节点下创建了一个叫做/zk-test的节点,该节点内容就是123,同时可以看到创建的 zk-test节点后面添加了一串数字以示区别
3、创建临时节点
使用create -e /zk-temp 123命令创建zk-te mp临时节
1 | create -e /zk-temp 123 |
临时节点在客户端会话结束后,就会自动删除,下面使用****quit****命令退出客户端
再次使用客户端连接服务端,并使用ls /命令查看根目录下的节点
可以看到根目录下已经不存在zk-tem P临时节点了
4、创建永久节点
使用 create /zk-p ermanent 123 命令创建 zk- permanent 永久节点
1 | create /zk-permanent 123 |
可以看到永久节点不同于顺序节点,不会自动在后面添加一串数字
5、读取节点
与读取相关的命令有ls命令和get命令 ls命令可以列出Zookee per指定节点下的所有子节点,但只能查看指定节点下的第一级的所有子节点;
1 | ls path |
其中,path表示的是指定数据节点的节点路径 get命令可以获取Zookee per指定节点的数据内容和属性信息。
1 | get path |
若获取根节点下面的所有子节点,使用*ls* ****/****命令即可
若想获取/zk-permanent的数据内容和属性,可使用如下命令:
1 | get /zk-permanent |
我们可以看到,第一行是节点/zk-permanent的数据内容,其他几行则是创建该 节点的事务ID (cZxid)、最后一次更新该节点的事务ID (mZxid)和最后一次更新该节点的时间(mtime)等属性信息
6、更新节点
使用set命令,可以更新指定节点的数据内容,用法如下
1 | set path data [version] |
其中,data就是要更新的新内容,version表示数据版本,在zookeeper中,节点的数据是有版本概 念的,这个参数用于指定本次更新操作是基于Znode的哪一个数据版本进行的,如将/zk-P ermanent节 点的数据更新为456,可以使用如下命令:
1 | set /zk-permanent 456 |
现在dataVersion已经变为1 了,表示进行了更新
7、删除节点
使用delete命令可以删除Zookee per上的指定节点,用法如下
1 | delete path [version] |
其中version也是表示数据版本,使用delete /zk- permanent命令即可删除/zk-p ermanent节点
值得注意的是,若删除节点存在子节点,那么无法删除 该节点,必须先删除子节点,再删除父节点
6. API
也就是通过JAVA来操作我们的Zookeeper,而不是直接通过Zookeeper客户端的命令行。
可以参考这篇文章:https://www.yuque.com/realskrman/bi4s0n/sf8hyq#VvaWB
7. 服务器角色
Leader
Leader服务器是Zookee per集群工作的核心,其主要工作有以下两个:
(1) 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
(2) 集群内部各服务器的调度者。
\1. 请求处理链
使用责任链来处理每个客户端的请求是Zookeeper的特色,Leader服务器的请求处理链如下:
可以看到,从 P re pRequest Processor 到 FinalRequest Processor 前后一共 7个请求处理器组成 了 leader 服务器的请求处理链
(1) Prep Request Processor。请求预处理器,也是leader服务器中的第一个请求处理器。在Zookee per 中,那些会改变服务器状态的请求称为事务请求(创建节点、更新数据、删除节点、创建会话等), Prep Request Process。r能够识别出当前客户端请求是否是事务请求。对于事务请求,
PrepRequestProcess。r处理器会对其进行一系列预处理,如创建请求事务头、事务体、会话检查、ACL 检查和版本检查等。
(2) ProposalRequestProcessor。事务投票处理器。也是Leader服务器事务处理流程的发起者,对 于非事务性请求,Propo salRequest Process。r会直接将请求转发到Commit Processor处理器,不再做 任何处理,而对于事务性请求,处理将请求转发到Commit Processor外,还会根据请求类型创建对应的 Pro po sal提议,并发送绐所有的Follower服务器来发起一次集群内的事务投票。同时, Propo salRequest Processor还会将事务请求交付绐SyncRequest Processor进行事务日志的记录。
(3) SyncRequest Processor。事务日志记录处理器。用来将事务请求记录到事务日志文件中,同时 会触发Zookee per进行数据快照。
(4) AckRequestProcessor。负责在SyncRequestProcessor完成事务日志记录后,向Proposal的投 票收集器发送ACK反馈,以通知投票收集器当前服务器已经完成了对该Proposal的事务日志记录。
(5) Commit Processor。事务提交处理器。对于非事务请求,该处理器会直接将其交付绐下一级处 理器处理;对于事务请求,其会等待集群内针对Prop osa l的投票直到该Prop osal可被提交,利用 Commit Processor,每个服务器都可以很好地控制对事务请求的顺序处理。
(6) ToBeCommit Processor。该处理器有一个toBeA pp lied队列,用来存储那些已经被
Commit Processor处理过的可被提交的P ro posal。其会将这些请求交付绐FinalRequest Processor处理 器处理,待其处理完后,再将其从toBeA PP lied队列中移除。
(7) FinalRequest Processor。用来进行客户端请求返回之前的操作,包括创建客户端请求的响应, 针对事务请求,该处理器还会负责将事务应用到内存数据库中。
Follower
Follower服务器是Zookee per集群状态中的跟随者,其主要工作有以下三个:
(1)处理客户端非事务性请求(读取数据),转发事务请求绐Leader服务器。
(1) 参与事务请求P ro po sa l的投票。
(2) 参与Leader选举投票。
和leader—样,Follower也采用了责任链模式组装的请求处理链来处理每一个客户端请求,由于不 需要对事务请求的投票处理,因此Follower的请求处理链会相对简单,其处理链如下
和Leader服务器的请求处理链最大的不同点在于,Follower服务器的第一个处理器换成了 FollowerRequest Processor处理器,同时由于不需要处理事务请求的投票,因此也没有了 P ro po salRequest Processor 处理器。
(1) FollowerRequestProcessor 其用作识别当前请求是否是事务请求,若是,那么Follower就会将该请求转发绐Leader服务器, Leader服务器在接收到这个事务请求后,就会将其提交到请求处理链,按照正常事务请求进行处理。
(2) SendAckRequestProcessor 其承担了事务日志记录反馈的角色,在完成事务日志记录后,会向Leader服务器发送ACK消息以表明自 身完成了事务日志的记录工作
Observer
Observer是ZooKee per自3.3.0版本开始引入的一个全新的服务器角色。从字面意思看,该服务器充当 了一个观察者的角色其观察ZooKee per集群的最新状态变化并将这些状态变更同步过来。
Observer服务器在工作原理上和Follower基本是一致的,对于非事务请求,都可以进行独立的处理,而 对于事务请求,则会转发绐Leader服务器进行处理。和Follower唯一的区别在于,Observer不参与任 何形式的投票,包括事务请求Proposal的投票和Leader选举投票。简单地讲,Observer服务器只提供 非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
另外,Observer的请求处理链路和Follower服务器也非常相近,其处理链如下
另外需要注意的一点是,虽然在图中可以看到,Observer服务器在初始化阶段会将
SyncRequestProcess。r处理器也组装上去,但是在实际运行过程中,Leader服务器不会将事务请求的 投票发送绐Observer服务器。
8. 选举机制
1.初始化Leader选举。
集群模式特有,Zookeeper首先会根据自身的服务器ID(SID)、最新的
ZXID (lastLoggedZxid)和当前的服务器epoch (currentEpoch)来生成一个初始化投票,在 初始化过程中,每个服务器都会给自己投票。然后,根据zoo.cfg的配置,创建相应Leader选举算法 实现,Zookeeper提供了三种默认算法(LeaderElection、AuthFastLeaderElection、 FastLeaderElection),可通过zoo.cfg中的electionAlg属性来指定,但现只支持 FastLeaderElection选举算法。在初始化阶段,Zookeeper会创建Leader选举所需的网络I/O层 QuorumCnxManager,同时启动对Leader选举端口的监听,等待集群中其他服务器创建连接。
2.注册JMX服务。
3 检测当前服务器状态
运行期间,Quorum Peer会不断检测当前服务器状态。在正常情况下,Zookee per服务器的状态 在 LOOKING、LEADING、FOLLOWING/OBSERVING 之间进行切换。在启动阶段,Quorum Peer 的初始 状态是LOOKING,因此开始进行Leader选举。
4. Leader 选举
ZooKee per的Leader选举过程,简单地讲,就是一个集群中所有的机器相互之间进行一系列投 票,选举产生最合适的机器成为Leader,同时其余机器成为Follower或是Observer的集群机器角 色初始化过程。关于Leader选举算法,简而言之,就是集群中哪个机器处理的数据越新(通常我们根 据每个服务器处理过的最大ZXID来比较确定其数据是否更新),其越有可能成为Leader。当然,如 果集群中的所有机器处理的ZXID—致的话,那么SID最大的服务器成为Leader,其余机器称为 Follower 和 Observer
9 参考文献
https://www.yuque.com/realskrman/bi4s0n/wrbzgy (☆☆☆☆☆)
语雀 比较详细 (本文大部分参考了此本章)https://www.cnblogs.com/ultranms/p/9585191.html (☆☆☆) 比较详细,目前理解有点难
https://www.cnblogs.com/mindzone/p/13448950.html (☆☆) 比较基础简洁