zookeeper全面总结

本文深入探讨了Zookeeper作为分布式协调服务的核心原理,包括Zookeeper架构、特点、数据结构、监听机制和内部一致性协议ZAB。重点讲解了Zookeeper在数据一致性、 Leader选举、事务处理和应用实例中的作用,以及与CAP理论和BASE理论的关系。

1. Zookeeper简介

1.1 Zookeeper是什么?

Zookeeper 是⼀个分布式协调服务的开源框架。 主要⽤用来解决分布式集群中应⽤用系统的一致性问题, 例例如怎样避免同时操作同一数据造成脏读的问题。分布式系统中数据存在一致性的问题!!

  • ZooKeeper 本质上是⼀个分布式的⼩文件存储系统。 提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理理。

  • ZooKeeper 提供给客户端监控存储在zk内部数据的功能,从⽽可以达到基于数据的集群管理。 诸如: 统一命名服务(dubbo)、分布式配置管理理(solr的配置集中管理)、分布式消息队列 (sub/pub)、分布式锁、分布式协调等功能。

1.2 zookeeper的架构组成

Leader:具有选举权利和被选举的权利,节点个数必须是基数个

  • Zookeeper 集群⼯作的核⼼角色

  • 集群内部各个服务器器的调度者。

  • 事务请求(写操作) 的唯一调度和处理者,保证集群事务处理的顺序性;对于 create, setData, delete 等有写操作的请求,则需要统一转发给leader 处理, leader 需要决定编号、执行操作,这个过程称为一个事务。

Follower:具有选举权利和被选举的权利,节点个数必须是基数个

  • 处理理客户端非事务(读操作) 请求,

  • 转发事务请求给 Leader;

  • 参与集群 Leader 选举投票 2n-1台可以做集群投票。 此外,针对访问量量⽐较⼤的 zookeeper 集群, 还可新增观察者角⾊。

Observer

  • 观察者角色,观察 Zookeeper 集群的最新状态变化并将这些状态同步过来,其对于⾮事务请求可以进⾏独立处理,对于事务请求,则会转发给 Leader服务器进行处理。
  • 不会参与任何形式的投票只提供非事务服务,通常用于在不不影响集群事务处理能力的前提下提升集群的非事务处理能力。增加了集群增加并发的读请求
  • 只是根leader同步数据,能够减轻zookeeper的服务压力(没有选举权和被选举权),到底有多少个没有关系,但是不能太多,如果太多,zookeeper同步数据的压力就增大

ZK也是Master/slave架构,但是与之前不同的是zk集群中的Leader不是指定而来,⽽是通过选举产生。

1.3 Zookeeper 特点

  1. Zookeeper:⼀个领导者(leader:⽼大),多个跟随者(follower:小弟)组成的集群。

  2. Leader负责进行投票的发起和决议,更新系统状态(内部原理)

  3. Follower用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票

  4. 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。

  5. 全局数据一致:每个server保存一份相同的数据副本,Client无论连接到哪个server,数据都是一 致的。

  6. 更新请求顺序进行(内部原理)

  7. 数据更新原子性,⼀次数据更新要么成功,要么失败。

ZooKeeper作为一个集群提供数据一致的协调服务,自然,最好的方式就是在整个集群中的各服务节点进行数据的复制和同步。通俗的讲,就是 zookeeper 以一个集群的方式对外提供协调服务,集群内部的所有节点都保存了一份完整的数据。其中一个主节点用来做集群管理提供写数据服务,其他的从节点用来同步数据,提供读数据服务。这些从节点必须保持和主节点的数据状态一致。

数据复制的好处:

​ 1、容错:一个节点出错,不至于让整个集群无法提供服务

​ 2、扩展性:通过增加服务器节点能提高 ZooKeeper 系统的负载能力,把负载分布到多个节点上

​ 3、高性能:客户端可访问本地 ZooKeeper 节点或者访问就近的节点,依次提高用户的访问速度

特点:

  • 最终一致性

    client 不论连接到哪个 Server,展示给它都是同一个数据视图,这是 ZooKeeper 最重要的性能。

  • 可靠性

    具有简单、健壮、良好的性能,如果消息 message 被到一台服务器接受,那么它将被所有的服务器接受。

  • 实时性

    ZooKeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网 络延时等原因,ZooKeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据 之前调用 sync() 接口。

  • 等待无关(wait-free)

    慢的或者失效的 client 不得干预快速的 client 的请求,使得每个 client 都能有效的等待。

  • 原子性

    更新只能成功或者失败,没有中间状态。

  • 顺序性

    包括全局有序和偏序两种:

    ​ 1、全局有序:如果在一台服务器上消息 a 在消息 b 前发布,则在所有 Server 上消息 a 都将在消息 b 前被发布;

    ​ 2、偏序:指如果一个消息 b 在消息 a 后被同一个发送者发布,a 必将排在 b 前面。

2. Zookeeper数据结构与监听机制

ZooKeeper数据模型Znode

image-20210902093926426

在 Zookeeper 中,每一个数据节点都是一个 ZNode,上图根目录下有两个节点,分别是:app1 和 app2,其中 app1 下⾯又有三个子节点,所有ZNode按层次化进行组织,形成这么一颗树,ZNode的节点路径标识⽅式和Unix文件系统路径非常相似,都是由一系列使用斜杠(/)进行分割的路径表示,开 发⼈员可以向这个节点写入数据,也可以在这个节点下⾯创建⼦节点。

2.1 ZNode 的类型

Zookeeper 节点类型可以分为三大类:

  • 持久性节点(Persistent)

  • 临时性节点(Ephemeral)

  • 顺序性节点(Sequential)

在开发中在创建节点的时候通过组合可以生成以下四种节点类型:持久节点、持久顺序节点、临时节点、临时顺序节点。不不同类型的节点则会有不同的⽣命周期。

  • **持久节点:**是Zookeeper中最常⻅见的一种节点类型,所谓持久节点,就是指节点被创建后会一直存在服务器,直到删除操作主动清除

  • **持久顺序节点:**就是有顺序的持久节点,节点特性和持久节点是⼀样的,只是额外特性表现在顺序上。 顺序特性实质是在创建节点的时候,会在节点名后⾯加上⼀个数字后缀,来表示其顺序。

  • **临时节点:**就是会被⾃动清理掉的节点,它的生命周期和客户端会话绑在⼀一起,客户端会话结束,节点会被删除掉。与持久性节点不同的是,临时节点不能创建子节点。

  • **临时顺序节点:**就是有顺序的临时节点,和持久顺序节点相同,在其创建的时候会在名字后面加上数字后缀。

事务ID

⾸先,先了解,事务是对物理和抽象的应用状态上的操作集合。往在现在的概念中,狭义上的事务通常指的是数据库事务,⼀般包含了一系列对数据库有序的读写操作,这些数据库事务具有所谓的ACID特 性,即原子性(Atomic)、⼀致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

而在ZooKeeper中,事务是指能够改变ZooKeeper服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新等操作。对于每⼀个事务请求,ZooKeeper都 会为其分配⼀个全局唯⼀的事务ID,⽤用 ZXID 来表示,通常是⼀个 64 位的数字。每一个 ZXID 对应一次更新操作,从这些ZXID中可以间接地识别出ZooKeeper处理这些更新操作请求的全局顺序

zk中的事务指的是对zk服务器状态改变的操作(create,update data,更新字节点);zk对这些事务操作都会编号,这个编号是⾃增长的被称为ZXID。

2.2 ZNode 的状态信息

 
#使⽤用bin/zkCli.sh 连接到zk集群
[zk: localhost:2181(CONNECTED) 2] get /zookeeper
cZxid = 0x0															# cZxid 就是 Create ZXID,表示节点被创建时的事务ID。
ctime = Wed Dec 31 19:00:00 EST 1969		# ctime 就是 Create Time,表示节点创建时间。
mZxid = 0x0															#	mZxid 就是 Modified ZXID,表示节点最后⼀一次被修改时的事务ID。
mtime = Wed Dec 31 19:00:00 EST 1969		#	就是 Modified Time,表示节点最后⼀一次被修改的时间。
pZxid = 0x0		# pZxid 表示该节点的⼦节点列表最后一次被修改时的事务ID。只有子节点列表变更才会更新pZxid,⼦节点内容变更不会更新。
cversion = -1					# cversion 表示⼦节点的版本号。
dataVersion = 0				# dataVersion 表示内容版本号。
aclVersion = 0				# aclVersion 标识acl版本
ephemeralOwner = 0x0	# ephemeralOwner 表示创建该临时节点时的会话sessionID,如果是持久性节点那么值为0
dataLength = 0				# dataLength 表示数据⻓度。
numChildren = 1				# numChildren 表示直系子节点数。

2.3 znode文件系统

不同于Linux,分为文件夹和文件,znode文件系统中只有znode节点(既可以存数据,也可以当作为文件夹)。

但是每个节点都必须要有一个唯一的绝对路径,每个节点都可以存储数据(根节点除外,可以存但是不建议存数据),每隔节点下都可以挂载子节点

虽然说zookeeper每个节点都存储了一份完整数据,但是不能存储大量的数据。所以znode只适合存储非常小量数据,不能超过1M,最好小于1K。

znode的分类:

  • 按照生命周期可以分为:

    • 短暂(ephemeral)(断开连接自己删除)
    • 持久(persistent)(断开连接不删除,默认情况)
  • 按照是否自带序列编号可以分为:

    • SEQUENTIAL(带自增序列编号,由父节点维护)
    • 非SEQUENTIAL(不带自增序列编号,默认情况)
节点类型 详解
PERSISTENT 持久化 znode 节点,一旦创建这个 znode 节点,存储的数据不会 主动消失,除非是客户端主动 delete
PERSISTENT_SEQUENTIAL 自动增加自增顺序编号的 znode 节点,比如 ClientA 去 zookeeper service 上建立一个 znode 名字叫做 /zk/conf,指定 了这种类型的节点后zk会创建 /zk/conf0000000000,ClientB 再 去创建就是创建 /zk/conf0000000001,ClientC 是创建 /zk/conf0000000002,以后任意 Client 来创建这个 znode 都会 得到一个比当前 zookeeper 命名空间最大 znod e编号 +1 的 znode,也就说任意一个 Client 去创建 znode 都是保证得到的 znode 编号是递增的,而且是唯一的 znode 节点
EPHEMERAL 临时 znode 节点,Client 连接到 zk service 的时候会建立一个 session,之后用这个 zk 连接实例在该 session 期间创建该类型的 znode,一旦 Client 关闭了 zookeeper 的连接,服务器就会清除 session,然后这个 session 建立的 znode 节点都会从命名空间消 失。总结就是,这个类型的 znode 的生命周期是和 Client 建立的 连接一样的。比如 ClientA 创建了一个 EPHEMERAL 的 /zk/conf 的 znode 节点,一旦 ClientA 的 zookeeper 连接关闭,这个 znode 节点就会消失。整个zookeeper service命名空间里就会删 除这个znode节点
EPHEMERAL_SEQUENTIA 临时自动编号节点 znode 节点编号会自动增加 但是会随session 消失而消失

注意点:

1、创建 znode 时设置顺序标识,znode 名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护

2、在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序

3、EPHEMERAL 类型的节点不能有子节点,所以只能是叶子结点

4、客户端可以在 znode 上设置监听器

2.4 ZNode的理解

1、znode 的约束(znode 的节点存储的最大数据是 1M,最好不要超过 1kb)为什么?

​ 每个节点都有相同的数据视图:每个节点都存储了这个 zookeeper 中的所有数据,每个节点的数据状态都和 leader 保持一致

​ a、同步的压力:写入过程至少要超过半数节点写成功才能认为该数据写成功,节点数越多,成功的难度越大

​ b、存储的压力:所有数据的规模超出单台服务器的存储能力

​ 2、znode 的分类

​ a、按照生命周期:临时节点EPHEMERAL 和 永久节点PERSISTENT

​ 持久类型(显示创建,显示删除,只有当使用显示命令来删除节点,否则这个节点知道被创建成功,则会一直存在)

​ 临时类型/短暂类型(跟会话绑定,那个会话创建的这个节点,如果这个会话断开,则这个会话创建的所有临时节点被系统删除)。

​ 每个znode节点必然都是由某一个session创建的。如果当前这个session断开,那么该znode节点会被自动删除

​ 比如 HDFS ,Kafka,HBase, 等各种组件使用 ZK 的时候,都是先建立跟 zk 的会话链接,通过这个会话链接去创建一个 临时znode 节点。如果这个链接断开,则 zk 系统会自动删掉这个链接创建的所有临时节点

​ b、按照是否带序列编号分,每个节点都各自维护了一个序列编号,当前节点的序列编号是由它的父节点维护的,编号是自增序列编号,和 mysql 的自增主键是一 样的道理

​ 1、 带

​ 2、 不带

​ create /a “data”

​ c、总结一下,总共分成四种:

​ 1、CreateMode.PERSISTENT 持久

​ 2、CreateMode.PERSISTENT_SEQUENTIAL 持久带序列编号

​ 3、CreateMode.EPHEMERAL 临时

​ 4、CreateMode.EPHEMERAL_SEQUENTIAL 临时带序列编号

​ 3、znode 的小知识

​ 临时节点的下面不能挂载子节点,临时节点,只能作为叶子节点

2.5 Watcher 机制

Zookeeper使用Watcher机制实现分布式数据的发布/订阅功能

⼀个典型的发布/订阅模型系统定义了一种 ⼀对多的订阅关系,能够让多个订阅者同时监听某⼀个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。

在 ZooKeeper 中,引⼊了 Watcher 机制来实现这种分布式的通知功能。ZooKeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的⼀些指定事件触发了这个 Watcher,那么Zk就会向指定客户端发送一个事件通知来实现分布式的通知功能。

image-20210902111639164

image-20210902111654487

注意:注册的监听在事件响应之后就失效了。那么怎么做到连续监听?请思考回答。

​ zookeeper默认监听触发一次就结束,所以需要重新实现WatchedEvent中的process方法,核心就是对watcher的循环调用。

WatchedEvent包含两方面重要信息:

  • 与zk服务器连接的状态信息

    可以调用watchedEvent.getState()方法获取与zk服务器连接的状态信息,状态信息取值主要包括SyncConnected、Disconnected、ConnectedReadOnly和AuthFailed等等。

  • 发生的具体事件类型信息

    watchedEvent.getState()方法只是获取与zk服务器连接的状态信息,但在同一个连接状态下,还会发生很多事件的类型。例如在zk中,我们可以watch一个节点的数据内容,当这个节点的数据被改变时,我们可以获取到这个事件。类似的还有子节点列表变化事件等等。这就需要我们在SyncConnected同一种连接状态下区分多个事件类型。可以通过watchedEvent.getType()方法获取具体的事件类型。事件类型的取值包括None、NodeCreated、NodeDeleted、NodeDataChanged和NodeChildrenChanged

监听工作原理:ZooKeeper 的 Watcher 机制主要包括客户端线程、客户端 WatcherManager、 Zookeeper 服务器三部分。客户端在向 ZooKeeper 服务器注册的同时,会将 Watcher 对象存储在客户端的 WatcherManager 当中。当 ZooKeeper 服务器触发 Watcher 事件后,会向客户端发送通知,客户端线程从 WatcherManager 中取出对应的 Watcher 对象来执行回调逻辑。

整个Watcher注册与通知过程如图所示。

image-20210902095335323

Zookeeper的Watcher机制主要包括客户端线程、客户端WatcherManager**、Zookeeper服务器器**三部 分。

具体⼯作流程为:

  • 客户端在向Zookeeper服务器注册的同时,会将Watcher对象存储在客户端的WatcherManager当中

  • 当Zookeeper服务器触发Watcher事件后,会向客户端发送通知

  • 客户端线程从WatcherManager中取出对应的Watcher对象来执行回调逻辑

3. Zookeeper内部原理

3.1 Leader选举

选举机制

半数机制:集群中半数以上机器存活,集群可用。所以Zookeeper适合安装奇数台服务器器。 Zookeeper虽然在配置文件中并没有指定Master和Slave。但是,Zookeeper⼯作时,是有一个节 点为Leader,其它为Follower,Leader是通过内部的选举机制产⽣的。

集群首次启动

假设有五台服务器组成的Zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这⼀点上,都是⼀样的。假设这些服务器依序启动,来看会发⽣什么

image-20210902095637687

全新集群选主

(1)服务器器1启动,此时只有它⼀台服务器启动了,它发出去的报文没有任何响应,所以它的选举状态一直是LOOKING状态。

(2)服务器2启动,它与最开始启动的服务器1进行通信,互相交换⾃己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1、2还是继续保持LOOKING状态。

3)服务器3启动,根据前⾯的理论分析,服务器3成为服务器1、2、3中的⽼大,⽽与上面不同的是,此时有三台服务器选举了它,所以它成为了了这次选举的Leader。

(4)服务器4启动,根据前面的分析,理论上服务器4应该是服务器1、2、3、4中最大的,但是由于前⾯已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了。

(5)服务器5启动,同4一样称为follower。

总结:zookeeper server的三种工作状态

  • LOOKING:当前Server不知道leader是谁,正在搜寻,正在选举

  • LEADING:当前Server即为选举出来的leader,负责协调事务

  • FOLLOWING:leader已经选举出来,当前Server与之同步,服从leader的命令

非全新集群选主

每个节点在选举时都会参考自身节点的zxid值(事务ID);优先选择zxid值大的节点称为Leader!!

那么,初始化的时候,是按照上述的说明进行选举的,但是当zookeeper运行了一段时间之后,有机器down 掉,重新选举时,选举过程就相对复杂了。

需要加入数据 version、serverid 和 逻辑时钟。

​ 逻辑时钟:这个值从0开始递增,每次选举对应一个值,也就是说:如果在同一次选举中,那么这个值应该是一致的;逻辑时钟值越大,说明这一次选举 leader 的进程更新,也就是每次选举拥有一个 zxid,投票结果只取 zxid 最新的

​ 数据 version:数据新的 version 就大,数据每次更新都会更新 version

​ server id:就是我们配置的 myid 中的值,每个机器一个

选举的标准就变成:

1、逻辑时钟小的选举结果被忽略,重新投票

2、统一逻辑时钟后,数据version大的胜出

3、数据version相同的情况下,server id大的胜出

根据这个规则选出 leader。

数据同步

选完 leader 以后,zk就进入状态同步过程。

详细步骤:

1、leader等待server连接;

2、follower连接leader,将最大的zxid发送给leader;

3、leader根据follower的zxid确定同步点;

4、完成同步后通知follower 已经成为uptodate状态;

5、follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

image-20210902110550450

3.2 ZAB一致性协议

1. 分布式数据⼀致性问题

为什么会出现分布式数据一致性问题?

  • 将数据复制到分布式部署的多台机器中,可以消除单点故障,防止系统由于某台(些)机器器宕机导致的不可用。

  • 通过负载均衡技术,能够让分布在不同地⽅的数据副本全都对外提供服务。有效提高系统性能。

在分布式系统中引入数据复制机制后,多台数据节点之间由于网络等原因很容易产生数据不一致的情 况。 举例

当客户端Client1将系统中的一个值K1由V1更新为V2,但是客户端Client2读取的是一个还没有同步更新的副本,K1的值依然是V1,这就导致了数据的不一致性。其中,常见的就是主从数据库之间的复制延时问题。

image-20210902100147125

2. ZAB协议

ZK就是分布式一致性问题的⼯业解决方案,paxos是其底层理论算法(晦涩难懂著名),其中zab,raft和众多开源算法是对paxos的⼯业级实现。ZK没有完全采用paxos算法,⽽是使⽤了⼀种称为Zookeeper Atomic Broadcast(ZAB,Zookeeper原⼦子消息广播协议)的协议作为其数据⼀致性的核心算法。

ZAB协议

ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种⽀持崩溃恢复和原⼦广播协议。

主备模式保证⼀致性

image-20210902100413372

ZK怎么处理集群中的数据?所有客户端写入数据都是写入Leader中,然后,由 Leader 复制到Follower 中。ZAB会将服务器数据的状态变更以事务Proposal的形式广播到所有的副本进程上,ZAB协议能够保证了事务操作的一个全局的变更序号(ZXID)。

⼴播消息

ZAB 协议的消息⼴广播过程类似于 ⼆二阶段提交过程。对于客户端发送的写请求,全部由 Leader 接收, Leader 将请求封装成⼀一个事务 Proposal(提议),将其发送给所有 Follwer ,如果收到超过半数反馈 ACK,则执⾏行行 Commit 操作(先提交⾃自⼰己,再发送 Commit 给所有 Follwer)。

  1. 发送Proposal到Follower

image-20210902100532387

  1. Leader接收Follower的ACK

    image-20210902100601515

  2. 超过半数ACK则Commit

    image-20210902100632041

不能正常反馈Follower恢复正常后会进入数据同步阶段最终与Leader保持⼀致!!

细节

  • Leader接收到Client请求之后,会将这个请求封装成⼀个事务,并给这个事务分配一个全局递增的唯⼀ ID,称为事务ID(ZXID),ZAB 协议要求保证事务的顺序,因此必须将每一个事务按照 ZXID 进行先后排序然后处理。

ZK集群为了保证任何事务操作能够有序的顺序执行,只能是 Leader 服务器接受写请求,即使是 Follower 服务器接受到客户端的请求,也会转发到 Leader 服务器进行处理。

zk提供的应该是最终一致性的标准。zk所有节点接收写请求之后可以在一定时间内保证所有节点都能看到该条数据!!

Leader 崩溃问题

Leader宕机后,ZK集群⽆法正常工作,ZAB协议提供了了一个⾼效且可靠的leader选举算法。

Leader宕机后,被选举的新Leader需要解决的问题

  • ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。
  • ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。

基于上⾯的⽬的,ZAB协议设计了⼀个选举算法:能够确保已经被Leader提交的事务被集群接受,丢弃还有提交的事务。

这个选举算法的关键点:保证选举出的新Leader拥有集群中所有节点最大编号(ZXID)的事务!!

3.3 Paxos算法和ZAB协议

Paxos算法是莱斯利·兰伯特(英语:Leslie Lamport)于1990年提出的一种基于消息传递且具有高度容错特性的一致性算法。

分布式系统中的节点通信存在两种模型:

  • 共享内存(Shared Memory)

  • 消息传递(Messages Passing)

基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程可能会慢、被杀死或者重启, 消息可能会延迟、丢失、重复,在基础Paxos场景中,先不考虑可能出现消息篡改即拜占庭错误 (Byzantine failure,即虽然有可能一个消息被传递了两次,但是绝对不会出现错误的消息)的情况。

Paxos算法解决的问题是在一个可能发生上述异常的分布式系统中如何就某个值达成一致,保证不论发 生以上任何异常,都不会破坏决议一致性。

Paxos算法使用一个希腊故事来描述,在Paxos中,存在三种角色,分别为:

  • Proposer(提议者,用来发出提案proposal),

  • Acceptor(接受者,可以接受或拒绝提案),

  • Learner(学习者,学习被选定的提案,当提案被超过半数的Acceptor接受后为被批准)

下面更精确的定义Paxos要解决的问题:

  • 决议(value)只有在被proposer提出后才能被批准

  • 在一次Paxos算法的执行实例中,只批准(chose)一个value

  • learner只能获得被批准(chosen)的value

ZooKeeper的选举算法有两种:一种是基于 Basic Paxos(Google Chubby采用)实现的,一种是基于 Fast Paxos(ZooKeeper采用)算法实现的。ZooKeeper 默认的选举算法为 Fast Paxos,并且 ZooKeeper在3.4.0 版本后只保留了 FastLeaderElection 算法。

ZooKeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做 ZAB协议(Zookeeper Atomic BroadCast)。

ZAB协议有两种模式,它们分别是:

  • 崩溃恢复模式(选主)

​ 当服务启动或者在领导者崩溃后,ZAB就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和follower之间具有相同的系统状 态。

  • 原子广播模式(同步)

​ 当ZooKeeper集群选举出leader同步完状态退出恢复模式之后,便进入了原子广播模式。所有的写请求都被 转发给leader,再由leader将更新proposal广播给follower

为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务。所有的提议 (proposal)都在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的数字,它高32位是 epoch 用 来标识 leader 关系是否改变,每次一个 leader 被选出来,它都会有一个新的 epoch,标识当前属于那 个 leader 的统治时期。低 32 位用于递增计数。

Basic Paxos流程:

1、选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server

2、选举线程首先向所有Server发起一次询问(包括自己)

3、选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的 serverid(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息 (serverid,zxid),并将这些信息存储到当次选举的投票记录表中

4、收到所有Server回复以后,就计算出id最大的那个Server,并将这个Server相关信息设置成下一次要 投票的Server

5、线程将当前id最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状 态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:

1、要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1

2、且存活的Server的数目不得少于n+1

每个 Server 启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的 server 还会从磁盘快照中恢复数据和会话信息,zookeeper 会记录事务日志并定期进行快照,方便在 恢复时进行状态恢复。

Fast Paxos 流程是在选举过程中,某Server首先向所有 Server 提议自己要成为 leader,当其它 Server 收到提议以后,解决 epoch 和 zxid 的冲突,并接受对方的提议,然后向对方发送接受提议完成的消 息,重复这个流程,最后一定能选举出 Leader

4. Zookeeper应⽤

ZooKeeper是⼀个典型的发布/订阅模式的分布式数据管理与协调框架,我们可以使用它来进行分布式数据的发布与订阅。另⼀⽅面,通过对ZooKeeper中丰富的数据节点类型进行交叉使用,配合Watcher 事件通知机制,可以非常⽅便地构建一系列分布式应用中都会涉及的核心功能,如数据发布/订阅、命名服务、集群管理、Master选举、分布式锁和分布式队列等。那接下来就针对这些典型的分布式应用场景来做下介绍

Zookeeper的两大特性:

  1. 客户端如果对Zookeeper的数据节点注册Watcher监听,那么当该数据节点的内容或是其子节点列表发生变更时,Zookeeper服务器就会向订阅的客户端发送变更通知。

  2. 对在Zookeeper上创建的临时节点,一旦客户端与服务器之间的会话失效,那么临时节点也会被自动删除

利⽤其两⼤特性,可以实现集群机器存活监控系统,若监控系统在/clusterServers节点上注册⼀个 Watcher监听,那么但凡进行动态添加机器的操作,就会在/clusterServers节点下创建⼀个临时节 点:/clusterServers/[Hostname],这样,监控系统就能够实时监测机器的变动情况。

4.1 服务器动态上下线监听

分布式系统中,主节点会有多台,主节点可能因为任何原因出现宕机或者下线,⽽任意一台客户端都要能实时感知到主节点服务器的上下线。

思路分析

image-20210902101338911

具体实现

服务端

package com.erainm.zk.test
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

erainm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值