Yarn与ZooKeeper

Yarn与ZooKeeper

Yarn是MapReduce引入的资源管理器,它的出现为集群在资源利用率、资源统一管理和数据共享等方面带来了巨大好处。ZooKeeper是一个分布式的、开源的协调服务框架,ZooKeeper出现就是为例减轻分布式应用实现协调服务的负担。

Yarn资源管理与调度

Yarn产生背景

在早期的Hadoop中,MRv1采用Master/Slave(M/S)框架,主要包括Client、JobTracker、TaskTracker和Task几个部分。其中JobTarcker负责整个系统的作业调度和资源管理,TaskTracker负责将本节点上资源的使用情况、节点健康状态和任务的运行进度汇报给JobTracker,同时接受JobTracker发送过来的命令并执行相应操作。
M/S架构的设计具有一定的缺陷,MRv1中存在的问题如下。

  1. 单点故障。JobTracker只有一个,如果JobTracker发生故障则整个集群就无法使用,削弱了集群的高可用性。
  2. 资源利用率低。MRv1采用的是基于槽位的资源分配模型,将槽位分为Map Slot和Reduce Slot,两种Slot由Map和Reduce任务独立使用,不能实现资源共享,导致资源利用率低。
  3. JobTarcker任务过重。JobTracker既要负责作业的调度和监控,又要负责资源的管理和分配。随着集群节点规模的扩大,JobTracker主节点压力过大,成为影响性能的瓶颈,限制了集群的扩展。
  4. 仅支持MapReduce计算框架。近几年出现了一些新的计算框架,如内存计算框架、流式计算框架和迭代式计算框架等,而MRv1不能支持这些新的计算框架。
    为了克服上述问题,Hadoop2.0对MRv1进行了重新设计,将资源管理和任务调度两个功能交给独立的模块负责,提出了MRv2和Yarn(yet another resource negotiator)。MRv2是计算框架,而Yarn独立负责资源管理和分配。通过这种功能划分,有效地降低了JobTracker的压力。Tarn为分布式应用提供了通用的资源管理框架,不但支持MapReduce应用,也支持几乎所有的其他分布式应用。
    在Yarn命令行中同样包含很多功能,用于日常运维、查看日志和提交作业。在终端,可输入yarn,查看各种选项。
    Yarn与ZooKeeper_第1张图片

Yarn的体系结构

Yarn体系结构
Yarn体系结构,Yarn同样采用Master/Slave结构,主要由ResourceManager(简称RM)、NodeManager(简称NM)、ApplicationMaster(简称AM)和Container等几部分组成。ResourceManager负责资源管理,ApplicationMaster负责任务监控和调度,NodeManager负责执行原TaskTracker的任务。
一个集群中通常有一个ResourceManager和多个NodeManager。

  1. ResourceManager是一个全局的资源管理器,负责整个系统资源管理和分配,整个集群只有一个。ResourceManager主要由两个组件构成:Scheduler和Applicaitons Manager。
    Scheduler是一个纯粹的调度器,负责为各种运行中的应用程序分配资源,它不负责应用程序的监控和状态跟踪等于应用程序相关的工作。Scheduler根据资源容量、队列以及其他因素的限制条件,将资源进行分配。
    Applications Manager是应用程序管理器,负责管理整个系统中所有应用程序的运行,包括应用程序的提交,与调度器协商资源以启动ApplicationMaster以及监控ApplicationMaster运行状态并在失败时重新启动等工作。
  2. NodeManager。NodeManger是每个节点上的资源和任务管理器。NodeManager定时地向ResourceManager汇报本节点上地资源使用情况和各个Container的运行状态。NodeManager接受并处理来自AM的启动和停止任务等各种请求。
  3. ApplicationMaster。用户提交的每个应用程序均会产生一个用于对其追踪和管理的ApplicationMaster。当用户提交作业时,ApplicationMaster与ResourceManager调度器协商从而获取资源(以Container形式)。将获得的资源进一步分配给内部的各个任务,如Hadoop平台上的Map任务和Reduce任务。ApplicationMaster与NodeManager通信,进行任务的启动、运行和停止。ApplicationMaster监控申请到的资源使用情况、任务的运行进度和状态,并在任务运行失败时进行恢复(重新为任务申请资源、重启任务等)。ApplicationMaster定时向ResourceManager发送“心跳”信息,汇报资源的使用情况和任务的执行状态。作业完成时,ApplicationMaster向ResourceManager注销容器。
    不同的ApplicationMaster分布在不同的节点上,它们之间不会互相影响。
  4. Container。Yarn以Container作为动态分配资源的单位。Container对任务运行环境进行抽象,封装CPU、内存等多维度的资源以及环境变量、启动命令等任务运行相关的信息。Yarn会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。
    一个应用程序所需的Container分为两种:一种是运行ApplicationMaster的Container,由ResourceManager向内部资源调度器申请;另一种是运行各类的Container,它由ApplicationMaster向ResourceManager申请,并通过ApplicationMaster与NodeManager通信来启动。
    ResourceManager Restart
    ResourceManager作为Yarn上的Master,负责集群的资源和调度管理,一旦发生单点故障,整个集群的资源将无法使用。为此,在Yarn中引入了新特性——ResourceManager Restart(重启)和ResourceManager HA(高可用性)。
    当发生故障时,应尽可能快地自动重启ResourceManager,另外,ResourceManager重启过程用户是感知不到的,ResourceManager Restart主要分为两个阶段。
  5. 阶段1——非工作保留RM重启。在Hadoop2.4.0版本之前,只有ResourceManager Restart阶段1是实现完成的。
    在Client提交Application时,RM会将应用程序元数据(ApplicationSubmissionContext)保留在可插拔的状态存储中,并保存应用程序的最终状态,例如,完成状态(失败、终止、已完成)和诊断时的诊断应用程序完成。此外,RM还会保存安全密钥、令牌等凭据,以便在安全的环境中工作。任何时候RM关闭,只要在状态存储中可以获取所需的信息(应用程序元数据以及在安全环境中运行的凭据),当RM重新启动时,它可以从状态存储中获取应用程序元数据并重新提交申请。如果Application在RM关闭前以及完成(Failed、Killed、Finished),RM不会重新提交Application。
    NodeManager和Cilent在RM的宕机时间内保持轮询RM状态知道RM恢复。当RM重新启动之后,他会通过心跳发送re - sync命令到所有的NodeManager和ApplicationMaster。到Hadoop2.4.0发布为止,NodeManager和ApplicationMaster处理此命令的行为是,NM会杀死它管理的所有Container,然后重新注册到RM。在RM看来,这些重新注册上来的NodeManager就相当于新加入的NM。AM(如MapReduce AM)在收到re-sync命令之后会关闭。在RM重新启动并加载所有应用程序元数据,并将状态存储的凭据填充到内存中之后,他将为尚未完成的每个应用程序创建一个新的ApplicationMaster并像往常一样重新启动该应用程序。
  6. 阶段2——保持工作的RM重启。从Hadoop2.6.0版本开始,进一步增强了RM重启功能来解决RM重启时可以不杀死任何在集群中运行的Application的问题。
    除了阶段1已经完成了基础性工作,即Application持久化和重新加载Application状态,阶段2主要侧重于重新构建完整的集群运行状态,主要是RM内部的中心调度器保持跟踪所有容器的生命周期、Application的余量和资源请求使用情况等。在这种方式下,RM不再需要像在阶段1中那么杀死AM并重新运行,Application就能够简单地与RM重新同步(re-sync),并从终端处继续它剩下的工作。
    RM利用NM发送的Container状态信息恢复自身的运行状态。当NM与重新启动的RM重新同步时,NM不会杀死容器。在重新注册之后,NM继续管理容器,并在重新注册时发送容器状态到RM。RM通过这些容器的信号重新构建容器实例和相关Application的调度状态。与此同时,AM需要重新发送未完成的资源请求到RM,因为RM可能会在关闭时丢失未完成的请求。Application利用它的AMRMClient库与RM通信,不用担心AM在重新同步时发送资源请求,因为它自动由库本身处理。
    另外,在Spark2.4.0之后,增加了高可用性功能。ResourceManager的高可用性可以"Active/Standby"的形式增加一个节点冗余,并利用ZooKeeper集群,把Active的ResourceManager状态信息写入ZooKeeper用于启动Standby状态的ResourceManager,以消除这个单点故障。

Yarn通信协议

在Yarn中,任何两个需要相互通信的组件之间都需要RPC协议,并且有且仅有一个。Yarn采用的是拉式(pull - based)通信模型,因为对于任何一个RPC协议,Clien总是主动连接Server。

  1. JobClient与RM之间的协议:JobClient通过该协议提交应用程序,查询应用程序状态等。
  2. Admin与RM之间的协议:admin通过该RPC协议更新系统配置文件。
  3. AM与RM之间的协议:AM通过该RPC协议向RM注册和撤销自己,并为各个任务申请资源。
  4. AM与NM之间的协议:AM通过该PRC协议要求NM启动或者停止Container,获取各个Container的使用状态等信息。
  5. NM与RM之间的协议:NM通过该RPC协议向RM注册,并定时发送心跳信息汇报当前节点的资源使用情况和Container运行情况。

Yarn执行过程

第一阶段:提交作业

  1. 在客户端通过创建JobClient实例,启动作业Job。
  2. 向ResourceManager请求获取一个新的作业ID(JobID),然后检查作业输出。例如,是否指定输出路径或输出路径是否已经存在,如果未指定输出路径或输出路径已经存在则放弃提交作业。计算作业的输入数据分片,若输入路径不存在则放弃提交作业。
  3. 如果输入输出检查没有错误,JobClient将作业运行所需要的资源复制到HDFS分布式文件系统中以JobID命名的目录下。这些资源包括本次作业相关的配置文件,计算所得的输入数据分片已经包含Mapper和Reducer类的jar文件等。
  4. 完成上述准备后,JobClient通过调用ResourceManager的submitApplication()方法发出作业提交请求。
    第二阶段:初始化作业
  5. ResourceManager接受到调用它的submitApplication()请求后,将该作业提交请求传递给调度器。调度器为该作业分配一个容器Container,然后ResourceManager在该Container内启动应用管理器ApplicationMaster进程,由NodeManager监控。
  6. MapReduce作业的ApplicationMaster是一个主类为MRAppMaster的Java进程,它首先向ResourceManager注册,使得用户可以通过ResourceManager查看作业的运行状态。然后实现作业的初始化,通过创造一些bookkeeping对象来对作业进行跟踪,获取任务的进度和完成情况。
  7. MRAppMaster从共享文件系统(如 HDFS)中读取计算好的输入分片信息,根据分片信息创建Map任务和Reduce任务。一般情况下,Map任务的数量是一个分片对应一个Map,而Reduce的数量可通过mapreduce.job.reduces属性确定。
    第三阶段:分配任务
  8. 如果作业很小,应用管理器会选择在其自己的JVM中运行任务。如果不是小作业,那么AM会向RM请求Container来运行所有的Map和Reduce任务。这些请求是通过"心跳"机制来传输的,请求信息中包括每个Map任务的数据位置(比如存放输入split的主机和对应机架信息)、内存需求信息等。AM利用这些信息来调度任务,尽量将任务分配给存储数据的节点,或者分配给与存放输入分片的节点相同的机架的节点。
    第四阶段:执行作业任务
  9. 当一个任务由资源管理器的调度器分配给一个Container后,应用管理器通过联系NM来启动Container。
  10. Container启动后,Map任务或Reduce任务由一个主类为YarnChild的Java应用程序执行。运行任务之前,首先将任务需要的资源本地化,包括作业的配置、JAR文件以及所有来自分布式婚车的文件。
  11. 在YarnChild进程中运行Map任务或Reduce任务。
    第五阶段:更新任务执行进度和状态
  12. Yarn中的任务将其进度和状态(包括counter)返回给ApplicationMaster,客户端每秒(通过mapreduce.client.progressmonitor.pollinterval设置)向ApplicationMaster请求进度更新,并反馈给用户。
    第六阶段:完成作业
  13. 除了向ApplicationMasrer请求作业进度,客户端可调用Job的waitForCompletion()方法检查作业完成情况。时间间隔可以通过mapreduce.client.completion.pollinterval来设置。作业完成之后,ApplicationMaster和Container会清理工作状态,OutputCommiter的作业清理方法也会被调用,作业的信息会被作业历史服务器存储以备之后用户核查。

Yarn的调度器

由于集群资源的有限性,Yarn应用发出的资源请求经常需要等待一段时间,才能得到需要的资源,资源调度器作为Yarn的核心组件,可根据特定的资源调度策略为应用合理分配资源。Yarn中的调度器是可插拔的,用户可根据需要自定义调度器,实现特定的资源调度策略。管理者可通过参数yarn.resourcemanager.scheduler.class设置资源调度器的主类,默认为org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
另外,对于所有的资源调度器,均需要实现以下接口:org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler。
另外,对于所有的资源调度器,均需要实现以下接口:org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler。该接口的定义如下

package org.apache.hadoop.yarn.server.resourcemanager.scheduler;

import java.io.IOException;
import java.util.List;
import org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate;
import org.apache.hadoop.classification.InterfaceStability.Evolving;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.api.records.NodeId;
import org.apache.hadoop.yarn.api.records.SchedulingRequest;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.recovery.Recoverable;

@LimitedPrivate({"yarn"})
@Evolving
public interface ResourceScheduler extends YarnScheduler, Recoverable {
    void setRMContext(RMContext var1);

    void reinitialize(Configuration var1, RMContext var2) throws IOException;

    List<NodeId> getNodeIds(String var1);

    boolean attemptAllocationOnNode(SchedulerApplicationAttempt var1, SchedulingRequest var2, SchedulerNode var3);

    void resetSchedulerMetrics();
}

Yarn采用的是双层资源调度模型;首先,ResourceManager中的资源调度器将资源分配给各个Application,然后,ApplicationMaster再进一步将资源分配给它内部的任务。这里主要介绍第一层的调度问题。
Yarn中有三种常见的调度策略:FIFO Scheduler(先进先出调度器)、Capacity Scheduler(容器调度器)和Fair Scheduler(公平调度器)。
FIFO Scheduler
FIFO(先进先出)调度器将应用放置到一个队伍中,按照应用提交的顺序为其分配资源。典型情况下,每个应用会使用整个集群,并且每个应用必须等待前一个应用执行完毕才会开始运行。由于大的应用可能会占用所有集群资源,因此,使用FIFO调度器,可能会出现小作业一直被阻塞的状态。FIFO调度器后来增加了设置作业优先级的功能(可通过参数设置),在选择要运行的下一个作业时,优先考虑作业优先级高的作业,但是优先级并不支持抢占,优先级高的作业仍然需要等到已经开始的优先级低的作业完成。该调度器简单易懂,不需要任何配置,但是不适合共享集群,在一个共享集群中,更适合使用容量调度器和公平调度器,这两种调度器都可以保证长时间运行的作业可以及时完成。
Capacity Scheduler
容器调度器是雅虎公司开发的多用户调度器,运行多个组织共享一个Hadoop集群,每个组织被配置为一个队列,调度器以队列为单位划分资源,每个队列可分配到全部集群资源的一部分。队列可进一步按照用户划分,队列中的不同用户共享该队列中的资源,此时每个用户也可称为一个队列。队列中的应用以FIFO方式调度,另外,为了避免队列过多地占用空闲资源,每个队列可设定资源的最低保证和最大使用上限,队列中的每个用户也可设定资源的使用上限。当一个队列的资源空闲时,可暂时将剩余资源共享给其他资源不够用的队列,这称为"弹性队列"。
Fair Scheduler
公平调度器旨在为所有运行的应用公平地分配资源。当只有一个大地作业运行时,该作业将会获取集群地全部资源,当第二个小作业提交后,Fair调度器会将一半地资源分享给小作业,两个作业可以公平地共享集群资源。
公平调度器是Facebook开发地多用户调度器,它和Capacity Scheduler相似,也是以队列为单位进行资源划分,每个队列可设定最低保证和最高使用上限,当某个队列有空闲资源时,可共享给其他队列使用。但是,Fair Scheduler和Capacity Scheduler也存在不同之处,主要体现在以下几个方面
1)队列内支持多种调度策略:在每个队列中,Fair Scheduler可选择FIFO、Fair或DRF策略为应用程序程序分配资源。
2)资源公平共享:按照队列中同时运行的作业的数量n,为每个作业分配1/n的资源。
3)负载均衡:Fair Scheduler提供了一个基于任务数目的负载机制,该机制尽可能将系统中的任务均匀分配给各个节点。
4)提高小应用程序响应时间:在FIFO策略中,若大作业先执行,小作业必须等到大作业完成才能执行。而Fair策略由于采用了最大最小公平算法,小作业也可以快速获取资源避免了饿死的状况。
其他调度器
Yarn中还包括自适应调度器、自学习调度器和动态优先级调度器等。

分布式协调服务ZooKeeper

ZooKeeper是一个开放源码的分布式应用程序协调服务,是谷歌公司的Chubby一个开源的实现,是Hadoop和HBase的重要组队。它是一个为分布式应用提供一致性服务的软件,提供的功能包括配置维护、域名服务、分布式同步、组服务等。

ZooKeeper概述

ZooKeeper是一个分布式的、开源的协调服务框架,服务于分布式应用程序。它提供一组简单的原语,使得分布式应用可以在此基础上构建更高级别的服务,例如,命名服务、配置管理、分布式同步和组服务等,既可以直接运用它去实现一致性、组管理、Leader选举和已存在的协议,也可以在此基础上建立自己特定的需求。ZooKeeper的数据结构类似文件系统目录数结构,易于编程且同时支持Java编程语言和C语言。
众所周知,不出错地实现协调服务是件很困难的事。它们特别容易出现竞争、死锁这样的错误,ZooKeeper的出现就是为了减轻分布式应用实现协调服务的负担。由于部分失败是分布式系统固有的特征,ZooKeeper并不能避免出现部分失败,因此ZooKeeper提供了一组工具,用来对构建分布式应用时部分失败的情况作出正确处理。另外,ZooKeeper注重高性能、高可靠性和严格的顺序访问,高性能使得ZooKeeper可以应用在大规模的分布式系统中,高可靠性可以避免发生单点故障,严格的顺序访问使得复杂的同步原语可以在客户端实现。另外,ZooKeeper的读写操作也十分快速,而且读要比写速度更快,比率大约为10:1,原因在于,在读的情况下,ZooKeeper可以提供给用户较旧的数据。
ZooKeeper具有以下特点

  1. 顺序一致性。来自客户端的更新操作将会按照它们的发送顺序被应用。
  2. 原子性。更新操作要么全部成功要么全部失败,没有部分操作成功或失败的情况。
  3. 单系统映像。客户端不管连接到那台服务器,都会看到相同的ZooKeeper服务视图。
  4. 可靠性。一旦一个更新操作成功,ZooKeeper将保持该更新状态不变,直到客户端再次更新它。
  5. 实时性。在特定时间范围内(大约十几秒),系统的客户端视图要保证是实时的。在这段时间里,客户端会看到系统的所有改变,否则客户端将检测到服务中断。
  6. 高可用性。ZooKeeper运行在一组机器之上,可以帮助系统避免出现单点故障,因此可用于构建可靠的应用程序。
  7. 简单。ZooKeeper的核心是一个精简的文件系统,它提供了一些简单的操作和一些额外的抽象操作,例如,排序和通知。

ZooKeeper数据模型

下面将分别介绍命名空间、znode、Watcher、Session,了解ZooKeeper数据模型。
分层命名空间
ZooKeeper可以看作是一个具有高可用性的文件系统,在这个文件系统中,没有文件和目录,而是统一使用"节点"的概念,称为znode。znode作为一个层次化的命名空间,既可以保存与之相关的数据,也可以保存其子znode的相关信息。
znode
在ZooKeeper的命名空间里,每个znode只有一个唯一的路径标识,且每个节点都由三个部分组成,分别是stat、data、children。stat为znode的状态信息,包括描述该znode的版本、权限等信息。data为与znode关联的数据。children为znode下的子节点信息。由于ZooKeeper是被设计用来实现协调服务,而不是用来大容量数据存储,因此一个znode能存储的数据被限制在1MB以内。
每个znode存储的数据都可以被进行读写操作。但是值得注意的是,由于ZooKeeper具有原子性特点,当对一个znode进行读写操作时,将得到它存储的所有数据;当对其进行写操作时,将替换掉它存储的所有数据。每个znode都有一个ACL来限制访问限制。
znode中的数据具有版本号。每当znode的数据发生变化,版本号就会增加。当客户端检索数据时会同时得到数据的版本号。当客户端执行一个更新或者删除操作时必须提供被修改节点数据的版本号。如果提供的版本号错误,则更新操作失败。
znode类型分为持久节点(persistent)、临时节点(ephemeral)和顺序节点(sequential)。所谓的持久节点是指一旦这个znode创建成功,除非主动进行znode的移除操作,否则节点会一直保存在ZooKeeper上;临时节点的生命周期是跟客户端的会话相关联的,一旦客户端会话失效,这个会话上的所有临时节点都会被自动移除,需要注意的是,临时节点不允许有子节点;而顺序节点是指名称中包含Zookeeper顺序号的znode,顺序号是一个单调递增的计数器,顺序节点通常与持久节点搭配使用,生成持久顺序节点。创建持久顺序节点时,用户需要请求ZooKeeper在节点路径末尾添加一个单调递增计数,这个计数对此父节点来说是唯一的。在分布式系统中,所有的事件可通过该顺序号进行全局排序,客户端便可以通过顺序号推断事件的顺序。
Watcher
客户端可以对znode设置监视点(Watcher)。znode的改变会触发Watcher,当Watcher被触发,ZooKeeper会向客户端发送一个通知。触发Watcher的事件包括节点数据改变、子节点改变、节点被删除和连接超时等。一个Watcher只能被触发一次。如果客户端在接收到一次监听事件后,还想继续接受节点发生改变的通知,需要重新设置Watcher。
Session
Session(会话)是客户端与ZooKeeper服务器端之间的通信通道。客户端与服务端之间的任何交互操作都与会话息息相关,如临时节点的生命周期、客户端请求的顺序执行、Watcher通知机制等。在ZooKeeper客户端与服务器端成功连接创建后,就创建了一个会话。

ZooKeeper架构

ZooKeeper服务通常由奇数个服务器构成。因为只要大多数服务器可用,ZooKeeper就是可用的。
客户端(Client)连接到单个服务器上。客户端和ZooKeeper服务器之间保持着一个TCP连接,通过该连接客户端可以发送请求、接收响应、接受监听事件及发送心跳等。如果TCP连接被中断了,客户端就会与另一台ZooKeeper服务器进行连接。
在ZooKeeper中,是有角色概念的。ZooKeeper集群中,分别有Leader(领导者)、Follower(跟随者)和Observer(观察者)三种类型的服务器角色。其中Follower和Observer同属于Learner(学习者)。

  1. Leader。Leader服务器在整个集群正常运行期间有且仅有一台,集群通过选举的方式选举出Leader服务器,负责进行投票的发起决议,更新系统状态。
  2. Follower。Follower负责参与Leader选举投票,接收客户端请求并向客户端返回结果。
  3. Observer。Observer不参与投票,只同步Leader的状态,引入这个角色主要是为了在不影响集群事务处理能力的前提下提升集群的非事务处理的吞吐量。另外,Observer可用接收客户端连接,并将写请求转发给Leader。
    Leader选举是保证分布式数据一致性的关键所在,因此对于集群启动而言, 很重要的一部分就是Leader选举。

ZooKeeper安装配置


详情可以参考
https://blog.csdn.net/shi_zi_183/article/details/115299001
https://blog.csdn.net/shi_zi_183/article/details/115628310
https://blog.csdn.net/shi_zi_183/article/details/116202903

ZooKeeper API

ZooKeeper支持Java编程语言和C语言,本节只介绍Java语言的ZooKeeper API使用方法。ZooKeeper API共包含5个包。

  1. org.apache.zookeeper
  2. org.apache.zookeeper.data
  3. org.apache.zookeeper.server
  4. org.apache.zookeeper.quorum
  5. org.apache.zookeeper.upgrade
    Maven需要引入

<dependency>
    <groupId>org.apache.zookeepergroupId>
    <artifactId>zookeeperartifactId>
    <version>3.6.2version>
dependency>

版本与自己集群zookeeper版本相同。

ZooKeeper类是编程时最经常使用的类文件,存放在包org.apache.zookeeper中。如果使用ZooKeeper服务,应用程序需要创建一个ZooKeeper实例。当客户端和ZooKeeper服务器建立连接,ZooKeeper系统将会分配给该连接会话一个ID值,并且客户端会周期性地向服务器发送心跳信息,维持该会话地连接,这样客户端便可调用ZooKeeper API对节点作为相应地处理。
以下的Java API均属于org.apache.zookeeper.ZooKeeper类,主要提供的常用的功能如下。
create

create(String path, byte[] data, List<ACL> acl, CreateMode createMode)

创建一个znode。各参数的含义:path为节点的路径,data为节点的初始数据,acl为节点控制访问列表,createMode为节点的类型。该方法最终的返回值是创建的节点的实际路径。
delete

delete(String path, int version)

删除给定路径节点的特定版本。给参数的含义:path为要删除节点的路径,version为节点的版本,当version为-1时,则匹配节点的任意版本。
exists
判断某一位置是否存在节点。若节点不存在,返回null;若节点存在且函数执行成功,则在该节点上创建一个watcher。
get data

getData(String path, boolean watch, Stat stat)

返回给路径节点的状态和数据。各参数含义:path为节点路径,watch取值为true且该函数执行成功,则在该节点上创建一个watcher,stat为节点的状态。
set data

public Stat setData(String path,byte[] data,int version)

为执行路径节点的特定版本设置数据。当version为-1时,则匹配节点的任意版本。若函数执行成功,则会触发getData函数在该节点创建的watcher。
get children

public List<String> getChildren(String path, Watcher watcher)

检索指定节点的子节点序列。若watch取值true且该函数执行成功,则在该节点上创建一个watcher。返回的子节点序列是无序的。
sync

public void sync(String path, VoidCallback cb, Object ctx)

等待数据被传播以实现同步数据。各参数含义:path为节点路径,cb为需要回调的程序,ctx为提供给回调的上下文。

编程实例

单个节点的创建、查询、修改及删除
此类包含两个主要的ZooKeeper函数,分别为createZKInstance()和ZKOperations()。其中createZKInstance()函数负责对ZooKeeper实例zk进行初始化。ZKOperations()函数是所定义的对节点的一系列操作,包括对ZooKeeper节点的创建、删除和修改。

package org.shizi;

import org.apache.zookeeper.*;

import java.io.IOException;

public class Zoo {
    private static final int SESSION_TIMEOUT=30000;
    private ZooKeeper zk;
    private Watcher wt=new Watcher() {
        public void process(WatchedEvent event) {
            System.out.println(event.toString());
        }
    };
    public void createZKInstance() throws IOException{
        //在zookeeper目录下使用bin/zkServer.sh status命令,查看leader的服务器的ip作为LeaderIP
        zk=new ZooKeeper("slave1:2181", SESSION_TIMEOUT,this.wt);
    }
    public void ZKOperations() throws KeeperException, InterruptedException {
        zk.create("/znode1","MyZnode1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        System.out.println("查看新创建节点znode1的数据:");
        System.out.println(new String(zk.getData("/znode1", false, null)));
        System.out.println("修改节点数据");
        zk.setData("/znode1","a new data".getBytes(),-1);
        System.out.println("节点znode1的新数据:");
        System.out.println(new String(zk.getData("/znode1", false, null)));
        System.out.println("删除节点znode1:");
        zk.delete("/znode1",-1);
        System.out.println("查看节点是否被删除:");
        System.out.println("节点状态[" + zk.exists("/znode1", false) + "]" + "节点已经被删除");
    }
    public void ZKclose() throws InterruptedException {
        zk.close();
    }
}

package org.shizi;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Test;

import java.io.IOException;

public class zookeeperTest {
    @Test
    public void ZooTest() throws IOException, KeeperException, InterruptedException {
        Zoo zoo=new Zoo();
        zoo.createZKInstance();
        zoo.ZKOperations();
        zoo.ZKclose();
    }
}

Yarn与ZooKeeper_第2张图片
在指定路径‘/’下创建多个节点,并一一列出

package org.shizi;

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SecondZK {
    private static final int SESSION_TIMEOUT=30000;
    private ZooKeeper zk;
    private Watcher wt=new Watcher() {
        public void process(WatchedEvent event) {
            System.out.println(event.toString());
        }
    };
    public void createZKInstance() throws IOException {
        zk=new ZooKeeper("master:2181,slave1:2181,slave2:2181",SESSION_TIMEOUT,this.wt);
    }
    public void ZKOpertions() throws KeeperException, InterruptedException {
        zk.create("/child1","I am the first son".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zk.create("/child2","I am the second son".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        zk.create("/child3","I am the third son".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    }
    public void ZKList(){
        String zPath="/";
        List<String>zooChildren=new ArrayList<String>();
        try{
            zooChildren=zk.getChildren(zPath,false);
            System.out.println("Znodes of /:");
            for (String zooChild:zooChildren){
                System.out.println(zooChild);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }
    public void ZKclose() throws InterruptedException {
        zk.close();
    }
}

    @Test
    public void SecondZKTest() throws IOException, KeeperException, InterruptedException {
        SecondZK zoo = new SecondZK();
        zoo.createZKInstance();
        zoo.ZKOpertions();
        zoo.ZKList();
        zoo.ZKclose();
    }

Yarn与ZooKeeper_第3张图片

你可能感兴趣的:(大数据学习,zookeeper,hadoop,big,data)