HDP 2.2 ( Hadoop 2.6 ) 集群的内存参数配置和参数调优 (Yarn/MapReduce2)

近期在根据集群上的各节点的物理机配置对集群的内存参数进行调整。  因此较系统的学习了一下hadoop里对资源调配的各组件的相关参数的含义。 作为示例的配置集群版本是2.6, hortonworks 2.2. 

首先要理解, hadoop 中 yarn 作为资源管理器, 起到一个底层的控制调配运算资源的作用。   yarn中资源的最小单位是container。 一个container 可以近似认为是一个运行的jvm。 
一个yarn集群中,有一个ResourceManager (中控的进程,可以存在于集群中的任何节点上), 还有若干个node manager (每个节点host 上有 一个node manager)每个node manager 管理一个到多个container。 
对于较小规模的hadoop集群, resource manager 和node manager可以并存于一个host上。 

因此yarn中配置的参数主要有如下几个。 
1. 在每个node manager一共有多少内存和cpu
yarn.node-manager.resource.memory-mb =117000
yarn.node-manager.resource.vcore=20
yarn.nodemanager.vmem-pmem-ratio=2.1
对于集群中不同硬件配置的节点, 上述两个配置可以根据物理机的实际配置来写。  注意的是, 必须给物理机留一些内存和计算资源给到操作系统使用不能用光。 建议这里的物理机配置到整个内存的80-90%左右。 我的节点的物理机为128GB 内存, 我这里配置了117GB. 
第三个是物理内存和虚拟 内存的比例。 后面会解释怎么用。 
2. 每个container的分配多少内存和cpu
当应用程序向resource manager 申请资源(即申请container )时, RM分配给一个container 多大的内存是按照一个最小单位进行分配的。 例如, 我们设置分配的最小单位为4GB, 则RM分配出来的container的内存一定是4G的倍数。  假设现在有一个程序向RM申请 5.1G的内存, 则RM会分配给它一个8GB的container去执行。 
yarn.scheduler.minimum-allocation-mb=4096
在实际执行map reduce的job中, 一个container实际上是执行一个map 或者reduce task的jvm的进程。 那么这个jvm在执行中会不断的请求内存,假设它的物理内存或虚拟内存占用超出了container的内存设定, 则node manager 会主动的把这个进程kill 掉。  这里需要澄清一点, JVM使用的内存实际上分为虚拟内存和物理内存。  JVM中所有存在内存中的对象都是虚拟内存, 但在实际运行中只有一部分是实际加载在物理内存中的。 我们使用linux的top 可以看到 VM, RES,    前者是虚拟内存,后者可以看成近似是实际占用的物理内存。 因此在设置mapreduce的task的 jvm opts 参数时, 应将heap size 设置的比container允许的最大虚拟内存小。 这样jvm 不会因为申请过多的内存而被node manager 强制关闭。 当然设置最大heap size 如果在执行中被超过, jvm就会报 OutOfMemoryException。 
同时还有一个参数,设定了RM可以分配的最大的container是多大。   假设应用程序向RM申请的资源超过了这个值, RM会直接拒绝这个请求。 
yarn.scheduler.maximum-allocation-mb

除了设置Yarn, 还需要设置mapreduce2
mapreduce2 是hadoop 上实际执行计算的引擎。 因此我们在前面所说的“应用程序”向yarn请求资源, 这里应用程序就是指mapreduce2 这个引擎。 mapreduce2 在逻辑上有几个概念: 一个job, 一个由app master 以及若干个 map task 和reduce task组成。  app master 负责向 Yarn的RM申请资源, 并将map 和reduce task 送到分配到的container去执行。 
mapreduce中可以设定 map task的默认使用的虚拟内存。  这个值是app master 在向 yarn申请用于map task的container时会使用的内存值。 
mapreudce.map.memory.mb=8192
mapreudce.reduce.memory.mb=8192
这个值是全局的, 这里可以看到mapreduce并不是很智能的, 他不知道某个job的map task需要使用多大的内存。 这个值应该根据集群大多数任务的特征来设定。  但是在我们执行一些需要很大内存的job的时候,可以在提交job时手工的overwrite这些参数。
另外,mapreduce2中还可以设置每个map、reduce task的子jvm进程的heapsize。  这个值应该比上面的task的虚拟内存值小(因为jvm除了heap还有别的对象需要占用内存), 如果jvm进程在执行中heap上的对象占用内存超过这个值, 则会抛出OutOfMemory Exception
mapreduce.map.java.opts=-Xmx7129m
mapreduce.reduce.java.opts=-Xmx7129m

一个典型的内存分配的流程
1. 用户提交hive sql
2. hive 将sql 翻译成若干map reduce job
3. mapreduce2  根据map task的默认内存分配, 向 yarn 申请资源。 
4. yarn 根据申请的资源大小,以及目前各node manager 当前可用的内存和cpu core 来决定 创建多大的container ,并分配给mapreduce2 的job

在container的执行过程中nodemanager 会定期检查每个container (及其所有子进程)的内存使用,包括物理的和虚拟的。 如果超出设定值, 则会强制杀掉该container。 那么这时这个mapreduce一定会fail。 解决的方法是, 在启动job时, 设置 mapreduce.map.memory.mb 、 mapreduce.reudce.memory.mb为一个更大的值,  mapreduce2也会向yarn申请更大的container。 

但是这个值是否越大越好呢 ? 不是。 这个值越大,会导致单个container的内存变多,虽然实际使用过程中用不到,但是可分配的container就变少了。 

适当的调小这个值,会使单个container所需的内存变小,因此集群会创建更多的container来执行任务,增加了并发度。更充分的利用节点 上的磁盘和cpu资源。

你可能感兴趣的:(云计算)