zookeeper详解

前言node

ZooKeeper 是一个开源的分布式协调服务,由雅虎建立,是 Google Chubby 的开源实现。分布式应用程序能够基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。算法

一、简介数据库

ZooKeeper 是一个开源的分布式协调服务,由雅虎建立,是 Google Chubby 的开源实现。分布式应用程序能够基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。apache

二、基本概念设计模式

本节将介绍 ZooKeeper 的几个核心概念。这些概念贯穿于以后对 ZooKeeper 更深刻的讲解,所以有必要预先了解这些概念。浏览器

2.1 集群角色安全

在 ZooKeeper 中,有三种角色:服务器

  • Leader网络

  • Follower数据结构

  • Observer

一个 ZooKeeper 集群同一时刻只会有一个 Leader,其余都是 Follower 或 Observer。

ZooKeeper 配置很简单,每一个节点的配置文件(zoo.cfg)都是同样的,只有 myid 文件不同。myid 的值必须是 zoo.cfg中server.{数值} 的{数值}部分。

zoo.cfg 文件内容示例:

ZooKeeper

在装有 ZooKeeper 的机器的终端执行 zookeeper-server status 能够看当前节点的 ZooKeeper 是什么角色(Leader or Follower)。

ZooKeeper

如上,node-20-104 是 Leader,node-20-103 是 follower。

ZooKeeper 默认只有 Leader 和 Follower 两种角色,没有 Observer 角色。为了使用 Observer 模式,在任何想变成Observer的节点的配置文件中加入:peerType=observer 并在全部 server 的配置文件中,配置成 observer 模式的 server 的那行配置追加 :observer,例如:

server.1:localhost:2888:3888:observer

ZooKeeper 集群的全部机器经过一个 Leader 选举过程来选定一台被称为『Leader』的机器,Leader服务器为客户端提供读和写服务。

Follower 和 Observer 都能提供读服务,不能提供写服务。二者惟一的区别在于,Observer 机器不参与 Leader 选举过程,也不参与写操做的『过半写成功』策略,所以 Observer 能够在不影响写性能的状况下提高集群的读性能。

2.2 会话(Session)

Session 是指客户端会话,在讲解客户端会话以前,咱们先来了解下客户端链接。在 ZooKeeper 中,一个客户端链接是指客户端和 ZooKeeper 服务器之间的TCP长链接。

ZooKeeper 对外的服务端口默认是2181,客户端启动时,首先会与服务器创建一个TCP链接,从第一次链接创建开始,客户端会话的生命周期也开始了,经过这个链接,客户端可以经过心跳检测和服务器保持有效的会话,也可以向 ZooKeeper 服务器发送请求并接受响应,同时还能经过该链接接收来自服务器的 Watch 事件通知。

Session 的 SessionTimeout 值用来设置一个客户端会话的超时时间。当因为服务器压力太大、网络故障或是客户端主动断开链接等各类缘由致使客户端链接断开时,只要在 SessionTimeout 规定的时间内可以从新链接上集群中任意一台服务器,那么以前建立的会话仍然有效。

2.3 数据节点(ZNode)

在谈到分布式的时候,通常『节点』指的是组成集群的每一台机器。而ZooKeeper 中的数据节点是指数据模型中的数据单元,称为 ZNode。ZooKeeper 将全部数据存储在内存中,数据模型是一棵树(ZNode Tree),由斜杠(/)进行分割的路径,就是一个ZNode,如 /hbase/master,其中 hbase 和 master 都是 ZNode。每一个 ZNode 上都会保存本身的数据内容,同时会保存一系列属性信息。

注:

这里的 ZNode 能够理解成既是Unix里的文件,又是Unix里的目录。由于每一个 ZNode 不只自己能够写数据(至关于Unix里的文件),还能够有下一级文件或目录(至关于Unix里的目录)。

在 ZooKeeper 中,ZNode 能够分为持久节点和临时节点两类。

  • 持久节点

所谓持久节点是指一旦这个 ZNode 被建立了,除非主动进行 ZNode 的移除操做,不然这个 ZNode 将一直保存在 ZooKeeper 上。

  • 临时节点

临时节点的生命周期跟客户端会话绑定,一旦客户端会话失效,那么这个客户端建立的全部临时节点都会被移除。

另外,ZooKeeper 还容许用户为每一个节点添加一个特殊的属性:SEQUENTIAL。一旦节点被标记上这个属性,那么在这个节点被建立的时候,ZooKeeper 就会自动在其节点后面追加上一个整型数字,这个整型数字是一个由父节点维护的自增数字。

2.4 版本

ZooKeeper 的每一个 ZNode 上都会存储数据,对应于每一个 ZNode,ZooKeeper 都会为其维护一个叫做 Stat 的数据结构,Stat 中记录了这个 ZNode 的三个数据版本,分别是 version(当前ZNode的版本)、cversion(当前ZNode子节点的版本)和 aversion(当前 ZNode 的 ACL 版本)。

2.5 状态信息

每一个 ZNode 除了存储数据内容以外,还存储了 ZNode 自己的一些状态信息。用 get 命令能够同时得到某个 ZNode 的内容和状态信息。以下:

ZooKeeper

在 ZooKeeper 中,version 属性是用来实现乐观锁机制中的『写入校验』的(保证分布式数据原子性操做)。

2.6 事务操做

在ZooKeeper中,能改变ZooKeeper服务器状态的操做称为事务操做。通常包括数据节点建立与删除、数据内容更新和客户端会话建立与失效等操做。对应每个事务请求,ZooKeeper 都会为其分配一个全局惟一的事务ID,用 ZXID 表示,一般是一个64位的数字。每个 ZXID 对应一次更新操做,从这些 ZXID 中能够间接地识别出 ZooKeeper 处理这些事务操做请求的全局顺序。

2.7 Watcher

Watcher(事件监听器),是 ZooKeeper 中一个很重要的特性。ZooKeeper容许用户在指定节点上注册一些 Watcher,而且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去。该机制是 ZooKeeper 实现分布式协调服务的重要特性。

2.8 ACL

ZooKeeper 采用 ACL(Access Control Lists)策略来进行权限控制。ZooKeeper 定义了以下5种权限。

  • CREATE: 建立子节点的权限。

  • READ: 获取节点数据和子节点列表的权限。

  • WRITE:更新节点数据的权限。

  • DELETE: 删除子节点的权限。

  • ADMIN: 设置节点ACL的权限。

注意:CREATE 和 DELETE 都是针对子节点的权限控制。

3. ZooKeeper典型应用场景

ZooKeeper 是一个高可用的分布式数据管理与协调框架。基于对ZAB算法的实现,该框架可以很好地保证分布式环境中数据的一致性。也是基于这样的特性,使得 ZooKeeper 成为了解决分布式一致性问题的利器。

3.1 数据发布与订阅(配置中心)

数据发布与订阅,即所谓的配置中心,顾名思义就是发布者将数据发布到 ZooKeeper 节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和动态更新。

在咱们日常的应用系统开发中,常常会碰到这样的需求:系统中须要使用一些通用的配置信息,例如机器列表信息、数据库配置信息等。这些全局配置信息一般具有如下3个特性。

  • 数据量一般比较小。

  • 数据内容在运行时动态变化。

  • 集群中各机器共享,配置一致。

对于这样的全局配置信息就能够发布到 ZooKeeper上,让客户端(集群的机器)去订阅该消息。

发布/订阅系统通常有两种设计模式,分别是推(Push)和拉(Pull)模式。

  • 推:服务端主动将数据更新发送给全部订阅的客户端。

  • 拉:客户端主动发起请求来获取最新数据,一般客户端都采用定时轮询拉取的方式。

ZooKeeper 采用的是推拉相结合的方式。以下:

客户端想服务端注册本身须要关注的节点,一旦该节点的数据发生变动,那么服务端就会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知后,须要主动到服务端获取最新的数据(推拉结合)。

3.2 命名服务(Naming Service)

命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,经过使用命名服务,客户端应用可以根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体一般能够是集群中的机器,提供的服务,远程对象等等——这些咱们均可以统称他们为名字(Name)。

其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表。经过在ZooKeepr里建立顺序节点,可以很容易建立一个全局惟一的路径,这个路径就能够做为一个名字。

ZooKeeper 的命名服务即生成全局惟一的ID。

3.3 分布式协调/通知

ZooKeeper 中特有 Watcher 注册与异步通知机制,可以很好的实现分布式环境下不一样机器,甚至不一样系统之间的通知与协调,从而实现对数据变动的实时处理。使用方法一般是不一样的客户端都对ZK上同一个 ZNode 进行注册,监听 ZNode 的变化(包括ZNode自己内容及子节点的),若是 ZNode 发生了变化,那么全部订阅的客户端都可以接收到相应的Watcher通知,并作出相应的处理。

ZK的分布式协调/通知,是一种通用的分布式系统机器间的通讯方式。

3.3.1 心跳检测

机器间的心跳检测机制是指在分布式环境中,不一样机器(或进程)之间须要检测到彼此是否在正常运行,例如A机器须要知道B机器是否正常运行。在传统的开发中,咱们一般是经过主机直接是否能够相互PING通来判断,更复杂一点的话,则会经过在机器之间创建长链接,经过TCP链接固有的心跳检测机制来实现上层机器的心跳检测,这些都是很是常见的心跳检测方法。

下面来看看如何使用ZK来实现分布式机器(进程)间的心跳检测。

基于ZK的临时节点的特性,可让不一样的进程都在ZK的一个指定节点下建立临时子节点,不一样的进程直接能够根据这个临时子节点来判断对应的进程是否存活。经过这种方式,检测和被检测系统直接并不须要直接相关联,而是经过ZK上的某个节点进行关联,大大减小了系统耦合。

3.3.2 工做进度汇报

在一个常见的任务分发系统中,一般任务被分发到不一样的机器上执行后,须要实时地将本身的任务执行进度汇报给分发系统。这个时候就能够经过ZK来实现。在ZK上选择一个节点,每一个任务客户端都在这个节点下面建立临时子节点,这样即可以实现两个功能:

  • 经过判断临时节点是否存在来肯定任务机器是否存活。

  • 各个任务机器会实时地将本身的任务执行进度写到这个临时节点上去,以便中心系统可以实时地获取到任务的执行进度。

3.4 Master选举

Master 选举能够说是 ZooKeeper 最典型的应用场景了。好比 HDFS 中 Active NameNode 的选举、YARN 中 Active ResourceManager 的选举和 HBase 中 Active HMaster 的选举等。

针对 Master 选举的需求,一般状况下,咱们能够选择常见的关系型数据库中的主键特性来实现:但愿成为 Master 的机器都向数据库中插入一条相同主键ID的记录,数据库会帮咱们进行主键冲突检查,也就是说,只有一台机器能插入成功——那么,咱们就认为向数据库中成功插入数据的客户端机器成为Master。

依靠关系型数据库的主键特性确实可以很好地保证在集群中选举出惟一的一个Master。

可是,若是当前选举出的 Master 挂了,那么该如何处理?谁来告诉我 Master 挂了呢?显然,关系型数据库没法通知咱们这个事件。可是,ZooKeeper 能够作到!

利用 ZooKeepr 的强一致性,可以很好地保证在分布式高并发状况下节点的建立必定可以保证全局惟一性,即 ZooKeeper 将会保证客户端没法建立一个已经存在的 ZNode。

也就是说,若是同时有多个客户端请求建立同一个临时节点,那么最终必定只有一个客户端请求可以建立成功。利用这个特性,就能很容易地在分布式环境中进行 Master 选举了。

成功建立该节点的客户端所在的机器就成为了 Master。同时,其余没有成功建立该节点的客户端,都会在该节点上注册一个子节点变动的 Watcher,用于监控当前 Master 机器是否存活,一旦发现当前的Master挂了,那么其余客户端将会从新进行 Master 选举。

这样就实现了 Master 的动态选举。

3.5 分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。

分布式锁又分为排他锁和共享锁两种。

3.5.1 排他锁

排他锁(Exclusive Locks,简称X锁),又称为写锁或独占锁。

若是事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只容许事务T1对O1进行读取和更新操做,其余任何事务都不能在对这个数据对象进行任何类型的操做(不能再对该对象加锁),直到T1释放了排他锁。

能够看出,排他锁的核心是如何保证当前只有一个事务得到锁,而且锁被释放后,全部正在等待获取锁的事务都可以被通知到。

如何利用 ZooKeeper 实现排他锁?

  • 定义锁

ZooKeeper 上的一个 ZNode 能够表示一个锁。例如 /exclusive_lock/lock节点就能够被定义为一个锁。

  • 得到锁

如上所说,把ZooKeeper上的一个ZNode看做是一个锁,得到锁就经过建立 ZNode 的方式来实现。全部客户端都去 /exclusive_lock节点下建立临时子节点 /exclusive_lock/lock。ZooKeeper 会保证在全部客户端中,最终只有一个客户端可以建立成功,那么就能够认为该客户端得到了锁。同时,全部没有获取到锁的客户端就须要到/exclusive_lock节点上注册一个子节点变动的Watcher监听,以便实时监听到lock节点的变动状况。

  • 释放锁

由于 /exclusive_lock/lock 是一个临时节点,所以在如下两种状况下,都有可能释放锁。

  • 当前得到锁的客户端机器发生宕机或重启,那么该临时节点就会被删除,释放锁。

  • 正常执行完业务逻辑后,客户端就会主动将本身建立的临时节点删除,释放锁。

不管在什么状况下移除了lock节点,ZooKeeper 都会通知全部在 /exclusive_lock 节点上注册了节点变动 Watcher 监听的客户端。这些客户端在接收到通知后,再次从新发起分布式锁获取,即重复『获取锁』过程。

3.5.2 共享锁

共享锁(Shared Locks,简称S锁),又称为读锁。若是事务T1对数据对象O1加上了共享锁,那么T1只能对O1进行读操做,其余事务也能同时对O1加共享锁(不能是排他锁),直到O1上的全部共享锁都释放后O1才能被加排他锁。

总结:能够多个事务同时得到一个对象的共享锁(同时读),有共享锁就不能再加排他锁(由于排他锁是写锁)

四、ZooKeeper在大型分布式系统中的应用

前面已经介绍了 ZooKeeper 的典型应用场景。本节将以常见的大数据产品 Hadoop 和 HBase 为例来介绍 ZooKeeper 在其中的应用,帮助你们更好地理解 ZooKeeper 的分布式应用场景。

4.1 ZooKeeper在Hadoop中的应用

在 Hadoop 中,ZooKeeper 主要用于实现 HA(Hive Availability),包括 HDFS的 NamaNode 和 YARN 的 ResourceManager 的 HA。同时,在 YARN 中, ZooKeepr 还用来存储应用的运行状态。

HDFS 的 NamaNode 和 YARN 的 ResourceManager 利用 ZooKeepr 实现 HA 的原理是同样的,因此本节以YARN为例来介绍。

ZooKeeper

从上图能够看出,YARN主要由ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)和Container四部分组成。其中最核心的就是ResourceManager。

ResourceManager 负责集群中全部资源的统一管理和分配,同时接收来自各个节点(NodeManager)的资源汇报信息,并把这些信息按照必定的策略分配给各个应用程序(Application Manager),其内部维护了各个应用程序的ApplicationMaster信息、NodeManager信息以及资源使用信息等。

为了实现HA,必须有多个ResourceManager并存(通常就两个),而且只有一个ResourceManager处于Active状态,其余的则处于Standby状态,当Active节点没法正常工做(如机器宕机或重启)时,处于Standby的就会经过竞争选举产生新的Active节点。

4.2 主备切换

下面咱们就来看看YARN是如何实现多个ResourceManager之间的主备切换的。

1. 建立锁节点

在 ZooKeeper 上会有一个/yarn-leader-election/appcluster-yarn的锁节点,全部的 ResourceManager 在启动的时候,都会去竞争写一个Lock子节点:/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb,该节点是临时节点。

ZooKeepr 可以为咱们保证最终只有一个ResourceManager可以建立成功。建立成功的那个 ResourceManager 就切换为 Active 状态,没有成功的那些 ResourceManager 则切换为 Standby 状态。

ZooKeeper

能够看到此时集群中 ResourceManager2 为 Active。

  1. 注册 Watcher 监听

    全部 Standby 状态的 ResourceManager 都会向 /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb 节点注册一个节点变动的Watcher监听,利用临时节点的特性,可以快速感知到Active状态的ResourceManager的运行状况。

  2. 主备切换

    当Active状态的ResourceManager出现诸如宕机或重启的异常状况时,其在ZooKeeper上链接的客户端会话就会失效,所以/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb节点就会被删除。此时其他各个Standby状态的ResourceManager就都会接收到来自ZooKeeper服务端的Watcher事件通知,而后会重复进行步骤1的操做。

以上就是利用 ZooKeeper 来实现 ResourceManager 的主备切换的过程,实现了 ResourceManager 的HA。

HDFS 中 NameNode 的 HA 的实现原理跟 YARN 中 ResourceManager 的 HA 的实现原理相同。其锁节点为 /hadoop-ha/mycluster/ActiveBreadCrumb。

4.3 ResourceManager状态存储

在 ResourceManager 中,RMStateStore 可以存储一些 RM 的内部状态信息,包括 Application 以及它们的 Attempts 信息、Delegation Token 及 Version Information 等。须要注意的是,RMStateStore 中的绝大多数状态信息都是不须要持久化存储的,由于很容易从上下文信息中将其重构出来,如资源的使用状况。在存储的设计方案中,提供了三种可能的实现,分别以下。

  • 基于内存实现,通常是用于平常开发测试。

  • 基于文件系统的实现,如HDFS。

  • 基于 ZooKeeper 实现。

因为这些状态信息的数据量都不是很大,所以 Hadoop 官方建议基于 ZooKeeper 来实现状态信息的存储。在 ZooKeepr 上,ResourceManager 的状态信息都被存储在 /rmstore 这个根节点下面。

ZooKeeper

RMAppRoot 节点下存储的是与各个 Application 相关的信息,RMDTSecretManagerRoot 存储的是与安全相关的 Token 等信息。每一个 Active 状态的 ResourceManager 在初始化阶段都会从 ZooKeeper 上读取到这些状态信息,并根据这些状态信息继续进行相应的处理。

4.4 小结:

ZooKeepr 在 Hadoop 中的应用主要有:

  1. HDFS 中 NameNode 的 HA 和 YARN 中 ResourceManager 的 HA。

  2. 存储 RMStateStore 状态信息

五、ZooKeeper在HBase中的应用

HBase 主要用 ZooKeeper 来实现 HMaster 选举与主备切换、系统容错、RootRegion 管理、Region状态管理和分布式 SplitWAL 任务管理等。

5.1 HMaster选举与主备切换

HMaster选举与主备切换的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。

5.2 系统容错

当 HBase 启动时,每一个 RegionServer 都会到 ZooKeeper 的/hbase/rs节点下建立一个信息节点(下文中,咱们称该节点为”rs状态节点”),例如/hbase/rs/[Hostname],同时,HMaster 会对这个节点注册监听。当某个 RegionServer 挂掉的时候,ZooKeeper 会由于在一段时间内没法接受其心跳(即 Session 失效),而删除掉该 RegionServer 服务器对应的 rs 状态节点。

与此同时,HMaster 则会接收到 ZooKeeper 的 NodeDelete 通知,从而感知到某个节点断开,并当即开始容错工做。

HBase 为何不直接让 HMaster 来负责 RegionServer 的监控呢?若是 HMaster 直接经过心跳机制等来管理RegionServer的状态,随着集群愈来愈大,HMaster 的管理负担会愈来愈重,另外它自身也有挂掉的可能,所以数据还须要持久化。在这种状况下,ZooKeeper 就成了理想的选择。

5.3 RootRegion管理

对应 HBase 集群来讲,数据存储的位置信息是记录在元数据 region,也就是 RootRegion 上的。每次客户端发起新的请求,须要知道数据的位置,就会去查询 RootRegion,而 RootRegion 自身位置则是记录在 ZooKeeper 上的(默认状况下,是记录在 ZooKeeper 的/hbase/meta-region-server节点中)。

当 RootRegion 发生变化,好比 Region 的手工移动、从新负载均衡或 RootRegion 所在服务器发生了故障等是,就可以经过 ZooKeeper 来感知到这一变化并作出一系列相应的容灾措施,从而保证客户端老是可以拿到正确的 RootRegion 信息。

5.4 Region管理

HBase 里的 Region 会常常发生变动,这些变动的缘由来自于系统故障、负载均衡、配置修改、Region 分裂与合并等。一旦 Region 发生移动,它就会经历下线(offline)和从新上线(online)的过程。

在下线期间数据是不能被访问的,而且 Region 的这个状态变化必须让全局知晓,不然可能会出现事务性的异常。

对于大的 HBase 集群来讲,Region 的数量可能会多达十万级别,甚至更多,这样规模的 Region 状态管理交给 ZooKeeper 来作也是一个很好的选择。

5.5 分布式SplitWAL任务管理

当某台 RegionServer 服务器挂掉时,因为总有一部分新写入的数据尚未持久化到 HFile 中,所以在迁移该 RegionServer 的服务时,一个重要的工做就是从 WAL 中恢复这部分还在内存中的数据,而这部分工做最关键的一步就是 SplitWAL,即 HMaster 须要遍历该 RegionServer 服务器的 WAL,并按 Region 切分红小块移动到新的地址下,并进行日志的回放(replay)。

因为单个 RegionServer 的日志量相对庞大(可能有上千个 Region,上GB的日志),而用户又每每但愿系统可以快速完成日志的恢复工做。所以一个可行的方案是将这个处理WAL的任务分给多台 RegionServer 服务器来共同处理,而这就又须要一个持久化组件来辅助 HMaster 完成任务的分配。

当前的作法是, HMaster 会在 ZooKeeper 上建立一个 SplitWAL 节点(默认状况下,是/hbase/SplitWAL节点),将“哪一个 RegionServer 处理哪一个 Region”这样的信息以列表的形式存放到该节点上,而后由各个 RegionServer 服务器自行到该节点上去领取任务并在任务执行成功或失败后再更新该节点的信息,以通知 HMaster 继续进行后面的步骤。 ZooKeeper 在这里担负起了分布式集群中相互通知和信息持久化的角色。

5.6 小结:

以上就是一些 HBase 中依赖 ZooKeeper 完成分布式协调功能的典型场景。但事实上,HBase 对 ZooKeeper 的依赖还不止这些,好比 HMaster 还依赖 ZooKeeper 来完成 Table 的 enable/disable 状态记录,以及 HBase 中几乎全部的元数据存储都是放在 ZooKeeper 上的。

因为 ZooKeeper 出色的分布式协调能力及良好的通知机制,HBase在各版本的演进过程当中愈来愈多地增长了 ZooKeeper 的应用场景,从趋势上来看二者的交集愈来愈多。HBase 中全部对 ZooKeeper 的操做都封装在了 org.apache.hadoop.hbase.zookeeper 这个包中,感兴趣的同窗能够自行研究。

 以上所述是小编给你们介绍的Spring Boot 模块组成,但愿对你们有所帮助,若是你们有任何疑问请给我留言,小编会及时回复你们的!  Java学习资料(复制下段连接至浏览器便可) data:textml;charset=UTF-8;base64,5oGt5Zac5L2g77yM5p625p6E5biI5a2m5Lmg576k5Y+35pivNjg2NTc5MDE0Cg==

相关文章
相关标签/搜索