hadoop重用机制

2020-10-27 17:10:18 浏览数 (1)

hadoop重用机制

Hadoop1.0JVM重用及调优
什么是HadoopJVM重用 ?

Hadoop里每个task任务的执行都会启动JVM进程来运行。

启动一个新的JVM进程将耗时1秒左右,对于运行时间较长(比如1分钟以上)的job影响不大,但如果都是时间很短的task,那么频繁启停JVM会有开销。

注意:JVM重用技术不是指同一Job的两个或两个以上的task可以同时运行于同一JVM上,而是排队按顺序执行。

Hadoop中有个参数是mapred.job.reuse.jvm.num.tasks,默认是1,表示一个JVM上最多可以顺序执行的task数目(属于同一个Job)是1。也就是说一个task启一个JVM。

一个tasktracker最多可以同时运行的task数目由mapred.tasktracker.map.tasks.maximum和mapred.tasktracker.reduce.tasks.maximum决定,并且这两个参数在mapred-site.xml中设置。默认是2,注意这个数字指的是同一个job的task数量。

如果task属于不同的job,那么JVM重用机制无效,不同job的task需要不同的JVM来运行。

hadoop1.0的解决方案

mapred.job.reuse.jvm.num.tasks的参数值是否设置为1(即:jvm不重用,默认值),如果为1,不进行任何处理,否则又判断是否设置了mapred.map.task.debug.script, mapred.reduce.task.debug.script, keep.task.files.pattern, mapred.task.profile, keep.failed.task.files,只要设置了其中的任何的一项,则jvm都不会进行重用(即mapred.job.reuse.jvm.num.tasks的值永远为1,对于任何一个task,它都会新启动一个jvm来运行该task) 。

我们知道mapred.job.reuse.jvm.num.tasks的默认值为1,即:每一个task都新启动一个jvm来运行任务,而当值为-1时,则表示jvm可以无限制重用。再结合上面的分析,当mapred.job.reuse.jvm.num.task设置为-1时,比值为1少的是killJvmRunner和spawnNewJvm过程,而且在值为-1时,TaskTracker首先也是先判断当前节点是否有空闲的slot剩余,如果没空闲的slot槽位,才会判断当前分配的slot槽位中的jvm是否已经将当前的task任务运行完,如果task已经运行完,才会复用当前jvm(当前只针对同一个job的task才会进行jvm的复用)。因此当一个job的task(尤其是task的耗时很小)数目很大,由于频繁的jvm停启会造很大的开销,进行jvm的复用也可以使同一job的一些static的数据得到共享,从而使集群的性能得到极大的提升。但是jvm的重用也会造成在同一个jvm中的碎片增加,导致jvm的性能变差。但是这一负面影响不是很大,总的来说,jvm重用还是值得使用的,尽管相对于那些长时间且task数少的job来说,jvm重用几乎没有什么性能提升。

但是有一点值得我们注意的是,由于mapred.job.reuse.jvm.num.task是客户端参数(也可以在服务端Tasktracker节点上将其声明为final使之生效),在jvm重用时,会导致map(reduce)函数中的static类型的变量在使用时可能没有达到预期目的,因为再次使用该变量时,静态变量的值仍为上次task运行结束时的值。因此在使用该参数时,对于在map(reduce)函数中静态变量的使用,一定要小心,应该考虑是否需要对其进行初始化或者仍然使用上次使用的值(以达到数据共享目的) 。

Hadoop2.0JVM重用及调优
hadoop2.0 uber功能

在 Yarn(Hadoop MapReduce v2)里面,不再有参数mapred.job.reuse.jvm.num.tasks,但它也有类似JVM Reuse的功能——uber。据Arun的说法,启用该功能能够让一些任务的执行效率提高2到3倍,不过,由于Yarn的结构已经大不同于MapReduce v1中JobTracker/TaskTracker的结构,因此uber的原理和配置都和之前的JVM重用机制大不相同。

uber原理

Yarn的默认配置会禁用uber组件,即不允许JVM重用。我们先看看在这种情况下,Yarn是如何执行一个MapReduce job的。首先,Resource Manager里的Application Manager会为每一个application(比如一个用户提交的MapReduce Job)在NodeManager里面申请一个container,然后在该container里面启动一个Application Master。container在Yarn中是分配资源的容器(内存、cpu、硬盘等),它启动时便会相应启动一个JVM。此时,Application Master便陆续为application包含的每一个task(一个Map task或Reduce task)向Resource Manager申请一个container。等每得到一个container后,便要求该container所属的NodeManager将此container启动,然后就在这个container里面执行相应的task。等这个task执行完后,这个container便会被NodeManager收回,而container所拥有的JVM也相应地被退出。在这种情况下,可以看出每一个JVM仅会执行一Task, JVM并未被重用。

用户可以通过启用uber组件来允许JVM重用——即在同一个container里面依次执行多个task。在yarn-site.xml文件中,改变一下几个参数的配置即可启用uber的方法:

参数| 默认值 | 描述

参数

默认值

描述

mapreduce.job.ubertask.enable

false

是否启用user功能。如果启用了该功能,则会将一个“小的application”的所有子task在同一个JVM里面执行,达到JVM重用的目的。这个JVM便是负责该application的ApplicationMaster所用的JVM(运行在其container里)。

那具体什么样的application算是“小的application"呢?下面几个参数便是用来定义何谓一个“小的application"

参数

默认值

描述

mapreduce.job.ubertask.maxmap

9

map任务数的阀值,如果一个application包含的map数小于该值的定义,那么该application就会被认为是一个小的application

mapreduce.job.ubertask.maxreduces

1

reduce任务数的阀值,如果一个application包含的reduce数小于该值的定义,那么该application就会被认为是一个小的application。不过目前Yarn不支持该值大于1的情况

mapreduce.job.ubertask.maxbytes

dfs.block.size

application的输入大小的阀值。默认为dfs.block.size的值。当实际的输入大小不超过该值的设定,便会认为该application为一个小的application

当uber功能被启用时,首先,Resource Manager里的Application Manager会为每一个application在NodeManager里面申请一个container,然后在该container里面启动一个Application Master。containe启动时便会相应启动一个JVM。此时,如果uber功能被启用,并且该application被认为是一个“小的application”,那么Application Master便会将该application包含的每一个task依次在这个container里的JVM里顺序执行,直到所有task被执行完(“WIth ‘uber’ mode enabled, you’ll run everything within the container of the AM itself”)。这样Application Master便不用再为每一个task向Resource Manager去申请一个单独的container,最终达到了 JVM重用(资源重用)的目的。

在yarn-site.xml里的配置示例
代码语言:javascript复制
 <!-- 开启uber模式(针对小作业的优化) --> 

   <property>

   <name>mapreduce.job.ubertask.enable</name> 

    <value>true</value> 

   </property>

  <!-- 配置启动uber模式的最大map数 --> 

    <property>

     <name>mapreduce.job.ubertask.maxmaps</name> 

   <value>9</value> 

</property>

  <!-- 配置启动uber模式的最大reduce数 --> 

  <property> 

     <name>mapreduce.job.ubertask.maxreduces</name> 

     <value>1</value> 

  </property>

Hadoop2.0引入了 uber(小作业)优化模式,专门处理大量小文件的问题.

注:开启此机制之后,需要制定小作业的阈值.设定map任务数量和reduce任务数量阈值.

上述配置的含义:当一个job的map任务<=9并且 reduce任务数量<=1的时候,此job被认为是一个小job.则底层会开启JVM的重用机制.

如果一个job被判定不是一个小作业,即使开启了uber模式,也不会开启JVM重用机制.

hadoop关于"小文件的"一些问题
小文件的定义

小文件指的是那些size比HDFS 的block size(默认64M/1.0版本,128M/2.0版本)小的多的文件。如果在HDFS中存储海量的小文件,会产生很多问题。

大量小文件在HDFS中的问题

任何一个文件,目录和block,在HDFS中都会被表示为元数据信息,每一个元数据信息占用150 bytes的内存空间。所以,如果有10million个文件,每一个文件对应一个block,那么就将要消耗namenode 3G的内存来保存这些block的信息。如果规模再大一些,那么将会超出现阶段计算机硬件所能满足的极限。

不仅如此,HDFS并不是为了有效的处理大量小文件而存在的。它主要是为了流式的访问大文件而设计的。对小文件的读取通常会造成大量从datanode到datanode的seeks和hopping来retrieve文件,而这样是非常的低效的一种访问方式。

大量小文件在MapReduce中的问题

Map tasks通常是每次处理一个block的input(默认使用FileInputFormat)。如果文件非常的小,并且拥有大量的这种小文件,那么每一个map task都仅仅处理了非常小的input数据,并且会产生大量的map tasks,每一个map task都会消耗一定量的bookkeeping的资源。比较一个1GB的文件,默认block size为64M,和1Gb的文件,每一个文件100KB,那么后者每一个小文件使用一个map task,那么job的时间将会十倍甚至百倍慢于前者。

hadoop中有一些特性可以用来减轻这种问题:可以在一个JVM中允许task reuse,以支持在一个JVM中运行多个map task,以此来减少一些JVM的启动消耗(通过设置mapred.job.reuse.jvm.num.tasks属性,默认为1,-1为无限制)。

0 人点赞