前言

本章主要讲述大数据领域中最著名的批处理与离线处理计算框架——MapReduce,包括MapReduce的原理、流程、使用场景,以及Hadoop集群中负责统一的资源管理与调度的组件——Yarn,包括Yarn的定义、功能与架构、HA方案和容错机制,以及利用Yarn完成资源调配的常用方法。最后,我们还简单介绍华为为这些组件所提供的增强特性。
1 MapReduce和Yarn基本介绍
MapReduce概述

MapReduce基于Google发布的MapReduce论文设计开发,基于分而治之的思想,用于大规模数据集(大于1TB) 的并行计算和离线计算,具有如下特点:
- 高度抽象的编程思想:程序员仅需描述做什么,具体怎么做交由系统的执行框架处理。
- 良好的扩展性:可通过添加节点以扩展集群能力。
- 高容错性:通过计算迁移或数据迁移等策略提高集群的可用性与容错性。
资源调度与分配

在Hadoop1.0版本中,只有HDFS和MapReduce,而资源调度通过MRv1来进行,存在着很多缺陷:
- master是单点,故障恢复依赖于周期性的checkpoint,不保证可靠性,发生故障的时候会通知用户,由用户自行决定是否重新计算。
- 没有区分作业调度与资源调度。 MR在运行时,环境会有大量的Job并发,因此多样且高效的调度策略是非常重要的。
- 没有提到资源隔离与安全性,大量Job并发的时候,如何保证单个Job不占用过多的资源,如何保证用户的程序对系统而言是安全的,在Hadoop 1.0中是个大问题。
因此,针对Hadoop1.0中MRv1的不足,以及为了满足编程范式多样化的需求,Hadoop2.0中正式引入了Yarn框架,以便更好地完成集群的资源调度与分配。
Yarn概述

Apache Hadoop YARN (Yet Another Resource Negotiator),中文名为“另一种资源协调者”。它是一种新的Hadoop资源管理器,它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。
2 MapReduce和Yarn功能与架构
MapReduce过程

顾名思义,MapReduce计算过程可具体分为两个阶段,Map阶段和Reduce阶段。其中,Map阶段输出的结果就是Reduce阶段的输入。
可以把MapReduce理解为,把一堆杂乱无章的数据按照某种特征归纳起来,然后处理并得到最后的结果。
- Map面对的是杂乱无章的互不相关的数据,它解析每个数据,从中提取出key和value,也就是提取了数据的特征。
- 到了Reduce阶段,数据是以key后面跟着若干个value来组织的,这些value有相关性。在此基础上我们可以做进一步的处理以便得到结果。
MapReduce工作流程

Map阶段详解

Job提交前,先将待处理的文件进行分片 (Split)。MR框架默认将一个块 (Block) 作为一个分片。客户端应用可以重定义块与分片的映射关系。
Map阶段先把数据放入一个环形内存缓冲区,当缓冲区数据达到80%左右时发生溢写 (Spill),需将缓冲区中的数据写入到本地磁盘。
Reduce阶段详解

前面提到的MOF文件是经过排序处理的。当Reduce Task接收的数据量不大时,则直接存放在内存缓冲区中,随着缓冲区文件的增多,MR后台线程将它们合并成一个更大的有序文件,这个动作是Reduce阶段的Merge操作,过程中会产生许多中间文件,最后一次合并的结果直接输出到用户自定义的reduce函数。
当数据很少时,不需要溢写到磁盘,直接在缓存中归并,然后输出给Reduce。
Shuffle过程详解

Shuffle的定义:Map阶段和Reduce阶段之间传递中间数据的过程,包括Reduce Task从各个Map Task获取MOF文件的过程,以及对MOF的排序与合并处理
典型程序WordCount举例

WordCount程序功能

WordCount的Map过程

WordCount的Reduce过程

Yarn的组件架构

MapReduce On Yarn任务调度流程

Yarn HA方案

Yarn中的ResourceManager负责整个集群的资源管理和任务调度,Yarn高可用性方案通过引入冗余的ResourceManager节点的方式,解决了ResourceManager 单点故障问题。
Yarn AppMaster容错机制

3 Yarn的资源管理和任务调度
资源管理

每个NodeManager可分配的内存和CPU的数量可以通过配置选项设置 (可在Yarn服务配置页面配置)。
- yarn.nodemanager.resource.memory-mb:可以分配给容器的物理内存的大小
- yarn.nodemanager.vmem-pmem-ratio:虚拟内存跟物理内存的比值
- yarn.nodemanager.resource.cpu-vcore:可分配给容器的CPU核数
在Hadoop3.x版本中,YARN 资源模型已被推广为支持用户自定义的可数资源类型(support user-defined countable resource types),而不是仅仅支持 CPU 和内存。常见的可数资源类型,除了CPU和Memory以外,还包括GPU资源、软件licenses或本地附加存储器(locally-attached storage)之类的资源,但不包括端口 (Ports) 和标签 (Labels)。
YARN的三种资源调度器

在Yarn中,负责给应用分配资源的叫做Scheduler (调度器)。在YARN中,根据不同的策略,共有三种调度器可供选择:
- FIFO Scheduler:把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
- Capacity Scheduler:允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,通过设置多个队列的方式给多个组织提供服务。除此之外,队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了。在一个队列内部,资源的调度是采用的是FIFO策略。
- Fair Scheduler:为所有的应用分配公平的资源(对公平的定义可以通过参数来设置)。
容量调度器的介绍

容量调度器使得Hadoop应用能够共享的、多用户的、操作简便的运行在集群上,同时最大化集群的吞吐量和利用率。
容量调度器以队列为单位划分资源,每个队列都有资源使用的下限和上限。每个用户可以设定资源使用上限。管理员可以约束单个队列、用户或作业的资源使用。支持作业优先级,但不支持资源抢占。
在Hadoop 3.x中,OrgQueue 扩展了容量调度器,通过 REST API 提供了以编程的方式来改变队列的配置。这样,管理员可以在队列的administer_queue ACL中自动进行队列配置管理。
容量调度器的特点

容量保证:管理员可为每个队列设置资源最低保证和资源使用上限,所有提交到该队列的应用程序共享这些资源。
灵活性:如果一个队列中的资源有剩余,可以暂时共享给那些需要资源的队列,当该队列有新的应用程序提交,则其他队列释放的资源会归还给该队列。
支持优先级:队列支持任务优先级调度 (默认是FIFO)。多重租赁:支持多用户共享集群和多应用程序同时运行。为防止单个应用程序、用户或者队列独占集群资源,管理员可为之增加多重约束。
动态更新配置文件:管理员可根据需要动态修改配置参数,以实现在线集群管理。
资源分配模型

调度器维护一群队列的信息。用户可以向一个或者多个队列提交应用。
每次NM心跳的时候,调度器根据一定的规则选择一个队列,再在队列上选择一个应用,尝试在这个应用上分配资源。
调度器会优先匹配本地资源的申请请求,其次是同机架的,最后是任意机器的。
容量调度器的任务选择

调度时,首先按以下策略选择一个合适队列:
- 资源利用量最低的队列优先,比如同级的两个队列Q1和Q2,它们的容量均为30,而Q1已使用10,Q2已使用12,则会优先将资源分配给Q1。
- 最小队列层级优先,例如:QueueA与QueueB.childQueueB,则QueueA优先。
- 资源回收请求队列优先。
然后按以下策略选择该队列中一个任务:
- 按照任务优先级和提交时间顺序选择,同时考虑用户资源量限制和内存限制。
队列资源限制 (1)

队列的创建是在多租户页面,当创建一个租户关联Yarn服务时,会创建同名的队列。比如先创建QueueA,QueueB两个租户,即对应Yarn两个队列。
队列资源限制 (2)

队列的资源容量 (百分比),有default、QueueA、QueueB三个队列,每个队列都有一个[队列名]。capacity配置:
- Default队列容量为整个集群资源的20%。
- QueueA队列容量为整个集群资源的10%。
- QueueB队列容量为整个集群资源的10%,后台有一个影子队列root-default使队列之和达到100% 。
队列资源限制 (3)

共享空闲资源
- 由于存在资源共享,因此一个队列使用的资源可能超过其容量 (例如QueueA.capacity),而最大资源使用量可通过参数限制。
- yarn.scheduler.capacity.root.QueueA.maximum-capacity(此参数也是在上页胶片展示的页面配置)
- 如果某个队列任务较少,可将剩余资源共享给其他队列,例如QueueA的maximum-capacity配置为100,假设当前只有QueueA在运行任务,理论上QueueA可以占用整个集群100%的资源。
用户限制和任务限制

用户限制和任务限制的参数可通过“租户管理”>“动态资源计划”>“队列配置”进行配置。
用户限制

每个用户最低资源保障 (百分比):
- 任何时刻,一个队列中每个用户可使用的资源量均有一定的限制,当一个队列中同时运行多个用户的任务时,每个用户的可使用资源量在一个最小值与最大值之间浮动。其中,最大值取决于正在运行的任务数目,而最小值则由
minimum-user-limit-percent决定。 - 例如,设置队列A的这个值为25,即
yarn.scheduler.capacity.root.QueueA.minimum-user-limit-percent=25,那么随着提任务的用户增加,队列资源的调整如图:

每个用户最多可使用的资源量 (所在队列容量的倍数):
- queue容量的倍数,用来设置一个user可以获取更多的资源。
yarn.scheduler.capacity.root.QueueD.user-limit-factor=1。
- 默认值为1,表示一个user获取的资源容量不能超过queue配置的capacity,无论集群有多少空闲资源,最多不超过maximum-capacity。
任务限制

- 最大活跃任务数:
- 整个集群中允许的最大活跃任务数,包括运行或挂起状态的所有任务,当提交的任务申请数据达到限制以后,新提交的任务将会被拒绝。默认值10000。
- 每个队列最大任务数:
- 对于每个队列,可以提交的最大任务数,以QueueA为例,可以在队列配置页面配置,默认是1000,即此队列允许最多1000个活跃任务。
- 每个用户可以提交的最大任务数:
- 这个数值依赖每个队列最大任务数。根据上面的数据, QueueA最多可以提交1000个任务,那么对于每个用户而言,可以向QueueA提交的最大任务数为1000 用户最低资源保障率 (假设25%) 用户可使用队列资源的倍数 (假设1)。
查看队列信息

队列的信息可以通过Yarn webUI进行查看,进入方法是“服务管理”>“Yarn”>“ResouceManager (主)”>“Scheduler”。
4 增强特性
增强特性 - Yarn动态内存管理

增强特性 - Yarn基于标签调度

总结
思考题
下面哪些是MapReduce的特点?( )
A. 易于编程
B. 良好的扩展性
C. 实时计算
D. 高容错性
Yarn中资源抽象用什么表示?( )
A. 内存
B. CPU
C. Container
D. 磁盘空间
下面哪个是MapReduce适合做的?( )
A. 迭代计算
B. 离线计算
C. 实时交互计算
D. 流式计算
容量调度器有哪些特点?( )
A. 容量保证
B. 灵活性
C. 多重租赁
D. 动态更新配置文件
