理解
Yarn
的内存管理与分配机制,对于我们搭建、部署集群,开发维护应用都是尤为重要的,对于这方面我做了一些调研供大家参考。
一、相关配置情况
关于
Yarn
内存分配与管理,主要涉及到了
ResourceManage
、
ApplicationMatser
、
NodeManager
这几个概念,相关的优化也要紧紧围绕着这几方面来开展。这里还有一个
Container
的概念,现在可以先把它理解为运行
map/reduce task
的容器,后面有详细介绍。
1.1 RM的内存资源配置, 配置的是资源调度相关
RM1
:
yarn.scheduler.minimum-allocation-mb
分配给
AM
单个容器可申请的最小内存
RM2
:
yarn.scheduler.maximum-allocation-mb
分配给
AM
单个容器可申请的最大内存
注:
l 最小值可以计算一个节点最大Container数量
l 一旦设置,不可动态改变
1.2 NM的内存资源配置,配置的是硬件资源相关
NM1
:
yarn.nodemanager.resource.memory-mb
节点最大可用内存
NM2
:
yarn.nodemanager.vmem-pmem-ratio
虚拟内存率,默认
2.1
注:
l RM1
、
RM2
的值均不能大于
NM1
的值
l NM1
可以计算节点最大最大
Container数量,
max(
Container)=NM1/RM2
l 一旦设置,不可动态改变
1.3 AM内存配置相关参数,配置的是任务相关
AM1
:
mapreduce.map.memory.mb
分配给
map
Container的内存大小
AM2
:
mapreduce.reduce.memory.mb
分配给
reduce
Container的内存大小
l 这两个值应该在
RM1
和
RM2
这两个值之间
l AM2
的值最好为
AM1
的两倍
l 这两个值可以在启动时改变
AM3
:
mapreduce.map.java.opts
运行
map
任务的
jvm
参数,如
-Xmx
,
-Xms
等选项
AM4
:
mapreduce.reduce.java.opts
运行
reduce
任务的
jvm
参数,如
-Xmx
,
-Xms
等选项
注:
1.
这两个值应该在
AM1
和
AM2
之间
二、对于这些配置概念的理解
知道有这些参数,还需理解其如何分配,下面我就一副图让大家更形象的了解各个参数的含义。
如上图所示,先看最下面褐色部分,
AM
参数
mapreduce.map.memory.mb=1536MB
,表示
AM
要为
map Container
申请
1536MB
资源,但
RM
实际分配的内存却是
2048MB
,因为
yarn.scheduler.mininum-allocation-mb=1024MB
,这定义了
RM
最小要分配
1024MB
,
1536MB
超过了这个值,所以
实际分配给
AM
的值为
2048MB(
这涉及到了规整化因子,关于规整化因子,在本文最后有介绍
)
。
AM
参数
mapreduce.map.java.opts=-Xmx 1024m
,表示运行
map
任务的
jvm
内存为
1024MB,
因为
map
任务要运行在
Container
里面,所以这个参数的值
略微小于mapreduce.map.memory.mb=1536MB
这个值。
NM
参数
yarn.nodemanager.vmem-pmem-radio=2.1
,
这表示
NodeManager
可以分配给
map/reduce Container 2.1
倍的虚拟内存,安照上面的配置,实际分配给
map Container
容器的虚拟内存大小为
2048*2.1=3225.6MB
,
若实际用到的内存超过这个值,
NM就会kill掉这个map Container,任务执行过程就会出现异常
。
AM
参数
mapreduce.reduce.memory.mb=3072MB
,表示分配给
reduce Container
的容器大小为
3072MB,
而
map Container
的大小分配的是
1536MB
,从这也看出,
reduce Container
容器的大小最好是
map Container
大小的两倍
。
NM
参数
yarn.nodemanager.resource.mem.mb=24576MB
,
这个值表示节点分配给
NodeManager
的可用内存,也就是节点
用来执行
yarn
任务的内存大小
。这个值要根据实际服务器内存大小来配置,比如我们
hadoop
集群机器内存是
128GB
,我们可以分配其中的
80%
给
yarn
,也就是
102GB
。
上图中
RM
的两个参数分别
1024MB
和
8192MB
,分别表示
分配给
AM map/reduce Container
的最大值和最小值
。
三、关于任务提交过程
3.1 任务提交过程
步骤
1
:
用户将应用程序提交到
ResourceManager
上;
步骤
2
:
ResourceManager
为应用程序
ApplicationMaster
申请资源,并与某个
NodeManager
通信,以启动
ApplicationMaster
;
步骤
3
:
ApplicationMaster
与
ResourceManager
通信,为内部要执行的任务申请资源,一旦得到资源后,将于
NodeManager
通信,以启动对应的任务。
步骤
4
:
所有任务运行完成后,
ApplicationMaster
向
ResourceManager
注销,整个应用程序运行结束。
3.2 关于Container
(
1
)
Container是
YARN
中资源的抽象,它封装了某个节点上一定量的资源(
CPU
和内存两类资源)。它跟
Linux
Container没有任何关系,仅仅是
YARN
提出的一个概念(从实现上看,可看做一个可序列化
/
反序列化的
Java
类)。
(
2
)
Container由
ApplicationMaster
向
ResourceManager
申请的,由
ResouceManager
中的资源调度器异步分配给
ApplicationMaster
;
(
3
)
Container的运行是由
ApplicationMaster
向资源所在的
NodeManager
发起的,
Container运行时需提供内部执行的任务命令(可以使任何命令,比如
java
、
Python
、
C++
进程启动命令均可)以及该命令执行所需的环境变量和外部资源(比如词典文件、可执行文件、
jar
包等)。
另外,一个应用程序所需的Container分为两大类,如下:
(
1
) 运行
ApplicationMaster
的
Container:这是由
ResourceManager
(向内部的资源调度器)申请和启动的,用户提交应用程序时,可指定唯一的
ApplicationMaster
所需的资源;
(
2
) 运行各类任务的
Container:这是由
ApplicationMaster
向
ResourceManager
申请的,并由
ApplicationMaster
与
NodeManager
通信以启动之。
以上两类Container可能在任意节点上,它们的位置通常而言是随机的,即
ApplicationMaster
可能与它管理的任务运行在一个节点上。
Container是
YARN
中最重要的概念之一,懂得该概念对于理解
YARN
的资源模型至关重要,
望大家好好理解。
注意:如下图,
map/reduce task
是运行在
Container
之中的,所以上面提到的
mapreduce.map(reduce).memory.mb
大小
都大于mapreduce.map(reduce).java.opts值的大小。
四、HDP平台参数调优建议
根据上面介绍的相关知识,我们就可以根据我们的实际情况作出相关参数的设置,当然还需要在运行测试过程中不断检验和调整。
以下是hortonworks给出的配置建议:
4.1 内存分配
Reserved Memory = Reserved for stack memory + Reserved for HBase Memory (If HBase is on the same node)
系统总内存
126GB
,预留给操作系统
24GB
,如果有
Hbase
再预留给
Hbase24GB
。
下面的计算假设
Datanode
节点部署了
Hbase
。
YARN以及MAPREDUCE所有可用的内存资源应该要除去系统运行需要的以及其他的hadoop的一些程序,总共保留的内存=系统内存+HBASE内存。
可以参考下面的表格确定应该保留的内存:
每台机子内存
|
系统需要的内存
|
HBase需要的内存
|
4GB
|
1GB
|
1GB
|
8GB
|
2GB
|
1GB
|
16GB
|
2GB
|
2GB
|
24GB
|
4GB
|
4GB
|
48GB
|
6GB
|
8GB
|
64GB
|
8GB
|
8GB
|
72GB
|
8GB
|
8GB
|
96GB
|
12GB
|
16GB
|
128GB
|
24GB
|
24GB
|
255GB
|
32GB
|
32GB
|
512GB
|
64GB
|
64GB
|
计算每台机子最多可以拥有多少个container,可以使用下面的公式:
containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
说明:
CORES为机器CPU核数
DISKS为机器上挂载的磁盘个数
Total available RAM为机器总内存
MIN_CONTAINER_SIZE是指container最小的容量大小,这需要根据具体情况去设置,可以参考下面的表格:
每台机子可用的RAM
|
container最小值
|
小于4GB
|
256MB
|
4GB到8GB之间
|
512MB
|
8GB到24GB之间
|
1024MB
|
大于24GB
|
2048MB
|
每个container的平均使用内存大小计算方式为:
RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
通过上面的计算,YARN以及MAPREDUCE可以这样配置:
配置文件
|
配置设置
|
默认值
|
计算值
|
yarn-site.xml
|
yarn.nodemanager.resource.memory-mb
|
8192 MB
|
= containers * RAM-per-container
|
yarn-site.xml
|
yarn.scheduler.minimum-allocation-mb
|
1024MB
|
= RAM-per-container
|
yarn-site.xml
|
yarn.scheduler.maximum-allocation-mb
|
8192 MB
|
= containers * RAM-per-container
|
yarn-site.xml (check)
|
yarn.app.mapreduce.am.resource.mb
|
1536 MB
|
= 2 * RAM-per-container
|
yarn-site.xml (check)
|
-Xmx1024m
|
= 0.8 * 2 * RAM-per-container
| |
mapred-site.xml
|
mapreduce.map.memory.mb
|
1024 MB
|
= RAM-per-container
|
mapred-site.xml
|
mapreduce.reduce.memory.mb
|
1024 MB
|
= 2 * RAM-per-container
|
mapred-site.xml
|
mapreduce.map.java.opts
|
|
= 0.8 * RAM-per-container
|
mapred-site.xml
|
mapreduce.reduce.java.opts
|
|
= 0.8 * 2 * RAM-per-container
|
举个例子:对于128G内存、32核CPU的机器,挂载了7个磁盘,根据上面的说明,系统保留内存为24G,不适应HBase情况下,系统剩余可用内存为104G,计算containers值如下:
containers = min (2*32, 1.8* 7 , (128-24)/2) = min (64, 12.6 , 51) = 13
计算RAM-per-container值如下:
RAM-per-container = max (2, (124-24)/13) = max (2, 8) = 8G
4.2containers 计算:
MIN_CONTAINER_SIZE = 2048 MB
containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
# of containers = min (2*2, 1.8*DISKS, (2048 * 0.5) / 256)=min(4,1.8*DISKS,4)=4
container
内存计算:
RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
RAM-per-container = max(256, 1024/4)
RAM-per-container = 256 MB
4.3Yarn 和 Mapreduce 参数配置:
yarn.nodemanager.resource.memory-mb = containers * RAM-per-container =4 *
yarn.scheduler.minimum-allocation-mb = RAM-per-container
yarn.scheduler.maximum-allocation-mb = containers * RAM-per-container
mapreduce.map.memory.mb = RAM-per-container
mapreduce.reduce.memory.mb = 2 * RAM-per-container
mapreduce.map.java.opts = 0.8 * RAM-per-container
mapreduce.reduce.java.opts = 0.8 * 2 * RAM-per-container
yarn.nodemanager.resource.memory-mb = 22 * 3630 MB
yarn.scheduler.minimum-allocation-mb = 3630 MB
yarn.scheduler.maximum-allocation-mb = 22 * 3630 MB
mapreduce.map.memory.mb = 3630 MB
mapreduce.reduce.memory.mb = 22 * 3630 MB
mapreduce.map.java.opts = 0.8 * 3630 MB
mapreduce.reduce.java.opts = 0.8 * 2 * 3630 MB
附:规整化因子介绍
为了易于管理资源和调度资源,
Hadoop YARN
内置了资源规整化算法,它规定了最小可申请资源量、最大可申请资源量和资源规整化因子,如果应用程序申请的资源量小于最小可申请资源量,则
YARN
会将其大小改为最小可申请量,也就是说,应用程序获得资源不会小于自己申请的资源,但也不一定相等;如果应用程序申请的资源量大于最大可申请资源量,则会抛出异常,无法申请成功;规整化因子是用来规整化应用程序资源的,应用程序申请的资源如果不是该因子的整数倍,则将被修改为最小的整数倍对应的值,公式为
ceil(a/b)*b
,其中
a
是应用程序申请的资源,
b
为规整化因子。
比如,在
yarn-site.xml
中设置,相关参数如下:
yarn.scheduler.minimum-allocation-mb
:最小可申请内存量,默认是
1024
yarn.scheduler.minimum-allocation-vcores
:最小可申请
CPU
数,默认是
1
yarn.scheduler.maximum-allocation-mb
:最大可申请内存量,默认是
8096
yarn.scheduler.maximum-allocation-vcores
:最大可申请
CPU
数,默认是
4
对于规整化因子,不同调度器不同,具体如下:
FIFO
和
Capacity Scheduler
,规整化因子等于最小可申请资源量,不可单独配置。
Fair Scheduler
:规整化因子通过参数
yarn.scheduler.increment-allocation-mb
和
yarn.scheduler.increment-allocation-vcores
设置,默认是
1024
和
1
。
通过以上介绍可知,应用程序申请到资源量可能大于资源申请的资源量,比如
YARN
的最小可申请资源内存量为
1024
,规整因子是
1024
,如果一个应用程序申请
1500
内存,则会得到
2048
内存,如果规整因子是
512
,则得到
1536
内存。
注:转载请说明出处