目录

​​一,ZooKeeper简介​​

​​1,什么是Zookeeper​​

​​2,基本特性​​

​​二,ZooKeeper原理​​

​​1,系统架构​​

​​1.1 角色分工​​

​​1.2 设计思想​​

​​1.3 为什么要引入Observer(ZK 3.3.0)?​​

​​2,数据模型​​

​​2.1 Znode​​

​​2.2 Znode Tree​​

​​2.3 会话session​​

​​2.4 Znode节点类型​​

​​2.5 Znode版本​​

​​2.6 Znode属性​​

​​3,数据读写​​

​​3.1 ZAB协议​​

​​3.2 数据写入​​

​​3.3 数据恢复​​

​​3.4 数据读取​​

​​4,Leader选举​​

​​4.1 服务器四种状态​​

​​4.2 启动期间leader选举​​

​​4.3 运行期间leader选举​​

​​5,Watcher机制​​

​​5.1 简介​​

​​5.2 工作机制​​

​​5.3 Watcher特性​​

​​三,Zookeeper应用场景​​

​​1,分布式锁​​

​​1.1 方式一​​

​​1.2 方式二​​

​​2,统一命名​​

​​3,配置管理​​

​​4,集群管理​​


文章内容来自:南京大学 / 星环科技课程,大数据理论与实践课程Ⅰ

一,ZooKeeper简介

1,什么是Zookeeper

高可用、高容错和高性能的分布式协调系统。

将复杂易错的分布式一致性服务封装起来,形成高效可靠的原语集,并提供简单易用的访问接口

为大型分布式系统提供关键、共性、高效和可靠的协调服务。

  • 数据发布订阅
  • 分布式锁
  • 统一命名
  • 配置管理
  • 集群管理(Master选举、节点上下线动态监测)

大数据开源技术体系的基础组件,无可替代。开源免费、简单易用、高可用、高容错、高性能。被HDFS、YARN、Kafka和HBase等技术高度依赖

2,基本特性

最终一致性:保证数据在各节点的副本最终能够达到一致状态,这是ZK最重要的功能;

有限实时性:不能保证一定能读到最新数据,要想实时获取最新数据,应先调用sync()进行强制同步;

原子性:集群所有服务器或者都成功执行了某一事务,或者都没有,不存在第三种情况;

顺序性:从同一客户端发起的事务请求,最终会严格按照其发起顺序应用到ZK中;

可靠性:服务端一旦成功执行了事务,则该事务所引起的数据变更会被一直保留;

单一视图:无论客户端连接到哪一台服务器,所看到的数据模型都是一致的;

二,ZooKeeper原理

1,系统架构

1.1 角色分工

四种角色:Leader、Follower、Observer和Client。

02-分布式协调服务ZooKeeper_大数据

1.2 设计思想

02-分布式协调服务ZooKeeper_大数据_02

Leader和Follwer遵循“Quorum仲裁机制(过半策略)”,参与事务处理和Leader选举的投票。

若Leader+Follwer的数量为m,则Quorum = m/2 + 1,只有投票数>=Quorum,事务和选举才判定成功。

Leader+Follwer的数量最好是奇数(2n+1),在不影响事务处理的前提下,最多可容忍n台宕机

例如:对于节点数为5和6的两个集群

①二者都最多容忍2台宕机,所以容灾能力相同(quorum5=3,quorum6=4,5-3=6-4=2台);

②前者的Quorum数为3,后者为4,前者更小,事务处理和选举的效率更高

1.3 为什么要引入Observer(ZK 3.3.0)?

1,在不影响写性能的前提下,提升读操作的性能和吞吐量

  • Follower数量越多,写操作的性能越差,吞吐量越小(因为Follower需要参与Quorum仲裁机制)
  • Observer不参与事务处理,数量再多也不影响集群的写性能
  • Observer不参与选主和事务处理,即使宕机也不影响集群的可用性

2,提升集群的可扩展性,以及大规模访问的承载能力

3,跨中心部署Observer ,为本地读请求提供快速响应

  • Leader和Follower部署在一个中心,很大程度上降低了网络延时对写性能的影响
  • 由于Observer要转发写请求和同步Leader状态,所以跨中心部署并不能彻底消除网络延时
  • 例如:阿里开源的跨机房同步系统Otter

2,数据模型

2.1 Znode

ZK的最小数据单元

节点有数据存储功能(非数据库),大小不能超过1M

节点中的数据应尽可能小,数据过大会导致ZK性能明显下降

如果确实要存储较大的数据,可将其放在数据库中,而存储地址放在Znode中。以HBase为例,元数据放在RegionServer中,元数据的寻址入口放在ZK中。

2.2 Znode Tree

Znode通过挂载子节点而形成的一个树状层次化命名空间,结构类似于Linux文件系统,但没有目录和文件,只有节点和子节点

绝对路径(非相对路径)作为节点名称,用于唯一标识节点(主节点挂掉,其余节点竞争创建znode,由于命名唯一,且只有一个节点可以创建成功,所以可以用来选主)

根节点为“/”,非根节点为不能以“/”结尾

02-分布式协调服务ZooKeeper_大数据_03

2.3 会话session

客户端为实现Znode读写操作而与ZK服务器建立的TCP长连接,即会话

在SessionTimeout时间内,客户端会通过心跳检测(Ping)或发送读写请求来激活和保持会话。同样,服务器要是一直未收到客户端消息,就会判定超时并关闭会话

在某一会话中,客户端请求以FIFO方式顺序执行

2.4 Znode节点类型

1,持久节点(PERSISTENT)

  • 节点默认类型,生命周期不依赖于客户端会话,只有客户端执行删除操作时,节点才会消失
  • 可以拥有子节点,也可以是叶节点

2,临时节点(EPHEMERAL)

  • 生命周期依赖于客户端会话,当会话结束时,节点会自动删除(也可手动删除)
  • 不能拥有子节点,只能是叶节点

3,顺序节点(SEQUENTIAL)

  • 带顺序编号的持久或临时节点
  • 创建顺序节点时,在路径后面会自动添加一个10位的节点编号(计数器),如 <path1>0000000001, <path2>0000000002, ,该编号在同一父节点下是唯一的

4,持久顺序节点(PERSISTENT_SEQUENTIAL)

5,临时顺序节点(EPHEMERAL_SEQUENTIAL)

2.5 Znode版本

Znode版本是形如0,1,2,…,N的单调递增数字,不是形如v1.2.1的软件版本

1,dataVersion(数据版本)

  • 当对Znode中的数据进行更新操作时,dataVersion自增1(即使数据值未发生变化)

2,cVersion(子节点版本)

  • 当Znode的子节点有变化时,cVersion自增1

3,aclVersion(ACL版本)

  • 当Znode的ACL(Access Control List, 访问控制列表)发生变更时,aclVersion自增1

4,利用版本确保分布式事务操作的原子性

  • 悲观锁:事务A执行期间,数据全程加锁,其他事务只能等待;适用于数据更新并发度较高的场景
  • 乐观锁:事务A提交更新请求前,先检查数据是否被其他事务修改过(通过比较版本进行写入校验),如修改过,则相关事务必须回滚;适用于数据更新并发度不高的场景

02-分布式协调服务ZooKeeper_分布式_04

2.6 Znode属性

02-分布式协调服务ZooKeeper_大数据_05

3,数据读写

3.1 ZAB协议

Zookeeper Atomic Broadcast,ZK原子广播协议。

基于该协议,ZK实现了Master/Slave架构下集群各节点副本数据的最终一致性。

包括两种模式:正常运行时的消息广播模式、Leader故障时的崩溃恢复模式。

3.2 数据写入

SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致。

ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑有关。

Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加

1,Follwer接收客户端写请求,并将其转发给Leader

2,Leader接收写请求,为其分配一个全局唯一的事务ID,Zxid(64位/单调递增)

3,Leader生成一个形如(Zxid, data)的事务提案Proposal(data是事务体),并将其放入各Follower对应的FIFO(顺序性)队列中(通过TCP协议实现),再按照FIFO策略把Proposal广播出去

4,Follower接收Proposal后,先以事务日志的形式落盘,再向Leader发送ack

5,当Leader接收到超过半数的ack之后(包括Leader自己),会向Follower发送commit命令,要求提交事务,同时自己在本地commit

6,Follower收到commit命令后提交事务,同时向客户端反馈结果

02-分布式协调服务ZooKeeper_分布式_06

3.3 数据恢复

(1)当Leader无法提供服务时,快速选举出一个新Leader

  • 原则:在所有参选Follower中,新Leader拥有Zxid最大的已提交事务
  • 确保数据最新:拥有最新的事务数据
  • 确保性能最优:软硬件条件最好、数据处理能力最强

(2)Follower与新Leader同步数据

  • 原则:对于某个事务,如果至少一个Follwer接收到Proposal并最终执行了commit,那么该事务数据就应该被永久保留
  • 例如:如果Leader把某个Proposal广播给所有Follwer之后宕机,数据该怎么处理?数据应该丢弃,因为该条数据并没有commit,不需要(没这个义务)进行保留。

3.4 数据读取

客户端直接从Follower或Observer读取数据

如果要确保读到最新数据,应该先调用sync()进行强制同步

4,Leader选举

4.1 服务器四种状态

LOOKING:寻找Leader状态,表示当前集群没有Leader,需要进行选举

LEADING:领导者状态,当前角色为Leader

FOLLOWING:跟随者状态,Leader选举已完成,当前角色为Follower

OBSERVING:观察者状态,当前角色为Observer,不参与选举和写事务

4.2 启动期间leader选举

参考​​@尚硅谷教育【源码级图文详解Zookeeper选举机制_大数据培训】​

1,服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;

2,服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid(SID)比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING

3,服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

4,服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;

5,服务器5启动,同4一样当小弟。

4.3 运行期间leader选举

当ZooKeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举:

  • 服务器初始化启动。
  • 服务器运行期间无法和Leader保持连接。

而当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态:

  • 集群中本来就已经存在一个Leader:当机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连接,并进行状态同步即可。
  • 集群中确实不存在Leader:按照EPOCH-》事务ID-》服务器ID的优先级顺序进行判定选举

5,Watcher机制

5.1 简介

以下部分内容参考​​@Jayicee【Zookeeper中的Watcher机制到底是啥?】​​

watcher机制是观察者模式在分布式场景下的实现,是zookeeper一个非常核心的机制,zookeeper提供的发布/订阅,监听节点变化(如节点的删除,内容的变化,或者子节点状态的变化)等核心功能都是基于watcher机制来是是实现的。

watcher机制涉及状态的监听,而这一状态其实包含了两种:

  • 客户端与服务端之间的连接状态(通知状态KeeperState)
  • 节点的状态(事件类型EventType)

02-分布式协调服务ZooKeeper_客户端_07

5.2 工作机制

1,注册Watcher监听器:客户端向ZK的某个Znode注册一个Watcher监听器

2,存储Watcher对象:客户端把Watcher对象存储到本地的WatchManager中 

3,处理Watcher事件:当服务端的指定事件触发了Watcher,会向客户端发送事件通知

4,回调Watcher对象:客户端根据通知状态和事件类型回调WatchManager中的Watcher对象,执行相应的业务逻辑

02-分布式协调服务ZooKeeper_大数据_08

5.3 Watcher特性

02-分布式协调服务ZooKeeper_zookeeper_09

三,Zookeeper应用场景

1,分布式锁

1.1 方式一

1,依据

  • 多个客户端同时创建同一个Znode节点(节点路径名唯一),只有一个客户端能够成功
  • Watcher机制

2,步骤

  1. 多个客户端同时在ZK上竞争创建临时节点“/Lock”(简称Lock节点,临时节点和session捆绑,session过期会自动删除,避免死锁) ,创建成功的客户端获得锁,并执行事务
  2. 其他客户端注册Watcher监听器,监听Lock节点
  3. 事务完成后,获得锁的客户端会删除Lock节点,释放锁,同时触发Watcher,通知其他客户端
  4. 其他客户端再次竞争创建Lock节点

3,缺点

  • 产生羊群效应,即当锁被释放后,如果抢占锁资源的竞争
  • 客户端太多,势必会影响性能

02-分布式协调服务ZooKeeper_客户端_10

1.2 方式二

1,依据

  • 临时顺序节点
  • Watcher机制

2,步骤

  1. 客户端在永久节点“/Lock”下创建临时顺序子节点,第一个客户端创建的子节点为“/Lock/Lock- 0”,第二个为“/Lock/Lock-1”,以此类推
  2. 客户端获取Lock节点的子节点列表,判断其创建的子节点的序号是否最小,如果是则获得锁,否则就监听序号排在其前一位的子节点
  3. 锁释放后,对应的子节点被删除,该节点序号后一位的子节点得到通知,重复步骤②直至获得锁

02-分布式协调服务ZooKeeper_大数据_11

2,统一命名

服务统一命名

  • 类似于JNDI(JNDI,The Java Naming and Directory Interface,Java命名和目录接口。是一组在Java应用中访问命名和目录服务的API。命名服务将名称和对象联系起来,使得我们可以用名称访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性),记录域名与IP之间的对应关系,域名作为访问入口
  • 按照Znode Tree层次结构组织服务名称
  • 将服务的地址、目录和提供者等信息存入Znode,通过服务名称来获取相关信息

全局唯一ID

  • UUID虽然可以保证分布式环境下的编号唯一,但缺点是无序、存储空间大和查询效率低
  • 利用Znode顺序节点,可以实现分布式环境下的编号生成器(ID生成器)

02-分布式协调服务ZooKeeper_zookeeper_12

3,配置管理

分布式环境下的配置信息同步

  • 集群中所有节点的配置信息需保持一致
  • 配置信息修改后,应快速同步到其他节点上

利用Znode和Watcher实现统一配置管理

  • 将配置信息写入Znode
  • 各节点监听Znode,一旦Znode的数据被修改,将通知各节点进行更新

02-分布式协调服务ZooKeeper_客户端_13

4,集群管理

实时掌握分布式系统中各节点的状态是集群管理的前提和基础

利用Znode和Watcher实现集群管理

1,将节点的状态信息写入Znode,利用Watcher监听Znode,以获取节点的实时状态变化

2,节点上下线动态监测

  • 新节点启动后,先在ZK中创建临时顺序Znode,这时会触发父节点上的监听器,并通知集群管理节点Master有新节点上线
  • 节点发生故障,失去与ZK的心跳连接,它创建的临时顺序Znode被自动删除,这时会触发父节点上的监听器,并通知Master节点下线

3,Master选举(ZooKeeper提供的选举机制,和ZooKeeper本身的选举机制不同)

  • 如果Master节点宕机,失去与ZK的心跳连接,那么它创建的临时Znode被自动删除,这时会触发该节点的Watcher,并通知所有Standby节点去竞争创建临时Znode
  • 成功创建临时Znode的Standby节点成为新的Master
  • 其他Standby节点在该Znode上注册监听器,等待下一次选举