Skip to content

Latest commit

 

History

History
126 lines (85 loc) · 11.8 KB

tune.md

File metadata and controls

126 lines (85 loc) · 11.8 KB

Hadoop调优

Hadoop集群搭建完成后,一般都要调整部分参数,以更好的利用集群。

内存

以下从3方面说下内存的调整。

进程

默认情况下,Hadoop为namendoe, datanode, resourcemanager, nodemanager等进程分配的内存为1G。namenode需要的内存可大致计算得到:namenode维护文件系统中每个数据块的引用,而每个文件系统含有的数据块数,文件名长度等不同,所以各集群的namenode对内存的需求也不同。一般保守估计namenode需要为每1百万个数据块分配1G内存空间。以100个节点的集群算,每节点有12 * 4T的磁盘空间,数据块为64MB,复本为3,则约有100 * 12 * 4 * 1 000 000 MB/(64MB * 3)=2500万个数据块,考虑到磁盘基本不会用完,所以该集群需要分配约20G内存给namenode。

MR2

除这些守护进程外,还需给任务调整内存分配,在MR2中,分别使用mapreduce.map.memory.mbmapreduce.reduce.memory.mb来限制map任务和reduce任务使用内存的大小,若任务使用内存使用超过mapreduce.map/reduce.memory.mb内存大小,会产生"Killing container"的问题。另外,map和reduce任务运行的JVM也可优化。若分配给任务运行的JVM内存太小,可能会产生"OutOfMemoryError"问题,若分配给其内存太大,可能会造成资源浪费。分配给每个任务的JVM大小由mapred.child.java.opts设置,默认为200MB,由于不大可能所有任务都使用同等大小jvm,因此可在客户端设置该属性(-Xmx)并覆盖配置文件中设置的值。在MR2版本中,若指定mapreduce.map.java.optsmapreduce.reduce.java.opts,会覆盖mapred.child.java.opts设置的值。mapreduce.map/reduce.memory.mb限制任务使用内存的总大小,mapreduce.map/reduce.java.opts限制任务JVM使用内存大小,一般设置后者为前者的75%~80%左右,剩余内存留给JAVA代码。

一般而言,推荐mapreduce.reduce.memory.mb的大小为mapreduce.map.memory.mb的2倍。

YARN

通过yarn.nodemanager.resource.memory-mb可指定每台nodemanager可分配的内存大小,如对于一台64G的nodemanager而言,若保留8G给操作系统及其他进程用,可将剩余的56G内存分给nodemanager用。

对于container而言,可通过yarn.scheduler.minimum-allocation-mbyarn.scheduler.maximum-allocation-mb来分配设置单个container可用的最小和最大内存。

Nodemanager会检查container中虚拟内存和物理内存的使用情况,yarn.nodemanager.vmem-pmem-ratio用于指定虚拟内存与物理内存的比值,默认为2.1,即每使用1M的物理内存,最多使用2.1M的虚拟内存。默认情况下,当container使用的内存超过设置物理内存或虚拟内存时,都会发生"Killing container"的情况。container中任务物理内存的设置为上面提过的mapreduce.map/reduce.memory.mb,若超出该值则报错。若map/reduce任务使用的虚拟内存大于yarn.nodemanager.vmem-pmem-ratio * mapreduce.map/reduce.memory.mb,也会报错。可通过yarn.nodemanager.pmem-check-enabledyarn.nodemanager.vmem-check-enabled停掉物理内存和虚拟内存的检查。

AM使用内存由yarn.app.mapreduce.am.resource.mb指定,AM的JVM的内存大小由yarn.app.mapreduce.am.command-opts指定。

整合

上面从几个点讲了内存的相关参数,这里引用MapReduce YARN Memory Parameters的一张图,整合上述几个参数。

Copy_of_Yarn_mem_params.jpg

RM每次分配给container的最小内存为1GB,AM会将每次申请的内存大小(mapreduce.map/reduce.memory.mb)进行调整,每次调整的内存大小为yarn.scheduler.increment-allocation-mb(在Fair Scheduler中,该值默认为512MB)* n+mapreduce.map/reduce.memory.mb,即若map container设置的内存(mapreduce.map.memory.mb)为1001MB,AM将从RM申请1GB+512MB=1.5GB,若map container申请的内存为1.G,AM将向RM申请1GB+512MB*2=2G。

vcore

vcore的调整基本同内存。nodemanager能分配的总的vcore数为yarn.nodemanager.resource.cpu-vcores,每个container分配的最大vcore数为yarn.scheduler.maximum-allocation-vcores,最小vcore数为yarn.scheduler.minimum-allocation-vcores,AM的调整因子为yarn.scheduler.increment-allocation-vcores,在Fair Scheduler中该值默认为1。map或reduce任务每次使用的vcore数为mapreduce.map/reduce.cpu.vcores。而AM使用vcore为yarn.app.mapreduce.am.resource.cpu-vcores

scheduler

一般情况下,各任务根据scheduler的设置运行在相应的queue中,因此,queue的设置也相当重要。CDH不支持Capacity Scheduler。Fair Scheduler有几个参数如下:

  • yarn.scheduler.fair.preemption
    开启抢占后,当一个pool的最小资源请求无法满足时,会从其他pool抢占部分资源。

  • yarn.scheduler.fair.sizebasedweight
    按每个app的size大小分配资源。默认关闭,即给所有app分配相同资源。

  • yarn.scheduler.fair.assignmultiple
    允许一个heartbeat分配多个container。当小任务很多时,开启这个参数能提高集群吞吐量。

这部分的设置和业务比较紧密,因此这里暂不赘述。

shuffle

shuffle做为MR奇迹发生的地方,优化好的话能很大程序提高job的运行速度。shuffle的具体过程可参考这里。总得来说应该多给shuffle分配资源,但同时也应确保map和reduce运行正常。优化分为两方面:1)减少磁盘读写次数;2)减少磁盘读写量。

对于前者来言,在map端,可调大mapreduce.task.io.sort.mb的值,减少spill次数;在reduce端的shuffle过程中,a).可调大mapreduce.reduce.shuffle.input.buffer.percent(占mapreduce.reduce.java.opts的比例)的值,以分配更多内存给reduce端的shuffle接收map端的数据。b). 当reduce端copy阶段的内存达到mapred.job.shuffle.merge.percent或map输出结果个数达到mapreduce.reduce.merge.inmem.threshold时,即做merge操作,一般而言,可将mapreduce.reduce.merge.inmem.threshold调整为0来做优化。c). 另外,若reduce函数需求内存不是很多,可提高mapreduce.reduce.input.buffer.percent的值来缓存部分merge合并数据给reduce以减小磁盘读写次数。

对于后者,可将map的中间结果和最终的输出结果进行压缩。对map的中间结果压缩,需设置mapreduce.map.output.compressTrue,并指定mapreduce.map.output.compress.codec为需要的编码解码器。对最终结果压缩,需设置mapreduce.output.fileoutputformat.compressTrue,并设置mapreduce.output.fileoutputformat.compress.codec 为需要的codec,若最终输出会写到SequenceFiles,还可设置mapreduce.output.fileoutputformat.compress.typeBLOCK来提高性能。

另外mapreduce.reduce.shuffle.parallelcopies定义了reduce并发copy map输出的线程个数,当map数较多时,可适当提高该值来提高copy速度。

HDFS其他调整

Uber

在MR1中有JVM重用的概念,在YARN中,相应的概念为Uber,对于小任务,Uber会省掉申请和退出JVM的次数,以提高Job执行次数。默认情况下YARN禁用Uber,此时AM会对job的每一个task都申请一个container,task执行完,该container会被回收。开启uber后,"小job"的所有task都在一个jvm运行。开启uber的参数为mapreduce.job.ubertask.enable,"小job"的定义为mapreduce.job.ubertask.maxmaps(默认为9),mapreduce.job.ubertask.maxreduces(默认为1,当前版本不支持reduce数大于1的情况),mapreduce.job.ubertask.maxbytes(默认为空)。

缓冲区大小

hadoop默认使用4KB的缓冲区辅助I/O操作,对于现在操作系统和硬件而言,这个值太过保守,增长缓冲区大小可显著提高性能,如128KB(131 072字节)更为常见。可通过core-site.xml中的io.file.buffer.size来进行设置。

HDFS块大小

默认情况下HDFS的块大小为64MB,可调大该值为256MB来降低namenode的内存压力。参数为dfs.blocksize。在HADOOP2.7中,该值已默认为128MB。

split块大小

block是物理块,split是逻辑块。一个split对应一个map输入。split的个数由Math.max(minSize, Math.min(goalSize, blockSize))决定,其中minSize由mapreduce.input.fileinputformat.split.minsize设置,默认为0;goalSize由goalSize = totalSize / (numSplits == 0 ? 1 : numSplits)得到,即文件大小除以用户设置的map数,若未设置map数,则默认为1;blockSize即为block大小。若多于一半的job其mapper运行时间都小于1分钟,可以考虑调高mapreduce.input.fileinputformat.split.minsize的值。

Short Circuit Local Reads

一般而言,Hadoop尽量将计算放在拥有数据的节点上,这使得数据和计算经常在一个节点上,形成大量的Local Reads 以影响网络传输。一般客户端读写数据的过程是先从datanode读取,然后再通过RPC把数据传输给DFSClient。若数据和读取端都在一个节点上,这样的过程虽然简单,但性能会有些影响,因为需要在datanode做一次中转。client直接读完文件的过程即所谓的"short-circuit"。

HDFS-2246HDFS-347提供两种短路读的方式。从配置复杂性和安全性角度讲,HDFS-2246中的方案都不太合适,因此一般主要使用HDFS-347的Unix Domain Socket方案。

配置Unix Domain Socket需要libhadoop.so,可通过hadoop checknative查看其是否已安装。short-circuit相关参数为dfs.client.read.shortcircuitdfs.domain.socket.path

Rebalance

参见Hadoop Rebalance,调整dfs.balance.bandwidthPerSec为50MB,在datanode的hdfs-site.xml中设置dfs.datanode.balance.max.concurrent.moves为100。

压缩

配置lzo压缩,见压缩

HA

HDFS和Yarn的HA都需开启。

YARN Web UI

调整hdfs的core-site.xml文件,增加如下项:

<property>
  <name>hadoop.http.staticuser.user</name>
  <value>yarn</value>
</property>

以免造成User [dr.who] is not authorized to view the logs的问题。

垃圾回收

fs.trash.interval设置为7天。

handler 调整

dfs.namenode.handler.count的值调整为datanode数的20倍大小,dfs.namenode.service.handler.count调整为datanode数的20倍大小,dfs.datanode.handler.count默认为3,调整为20。需要注意的是,每增加一个线程,相应的内存也需要增加。

HBase调整

复制

hbase.replication设置为true,hbase.region.replica.replication.enabled设置为true。

handlder 调整

hbase.master.handler.count调整为200,hbase.regionserver.handler.count调整为200,hbase.regionserver.metahandler.count调整为50。

ipc server callqueue

调整hbase-site.xml,增加如下项:

<property>
 <name>hbase.ipc.server.max.callqueue.size</name>
 <value>5368709120</value>
</property>

Reference