- 配置参数
Hadoop 0.20.*版本之前的参数配置文件为conf/hadoop-site.xml,Hadoop0.20.*版本之后将该配置文件分为core-site.xml、hdfs-site.xml、mapred-site.xml三个文件。
① 优化Map和Reduce任务数参数mapred.tasktracker.map.tasks.maximum和mapred.tasktracker.reduce.tasks.maximum决定了一台服务器上最多能同时运行的Map和Reduce任务数。
每个任务的创建和调度都要耗费若干秒的时间,一般情况下,若任务执行时间少于30~40s,就认为任务浪费了时间,可以采用减少任务数量的方法来解决这个问题。若每个任务运行超过30~40s,则可增加Map任务的数量,最好将Map的任务数设置为Map工作节点数的倍数。通常情况下,Reduce任务的数量应等于或是小于集群中Reduce工作节点数。此外,若一个MapReduce作业的输入数据大于1TB,则可通过增加数据块的大小来减少任务的数量。
在正常规模的集群中,集群中每个节点大概分配10~100个Map。若Map任务使处理器消耗较低的话,则可设置约300个左右的Map数。通常情况下,Map的数目是根据输入数据的大小来确定的,很多时候是取所有输入文件中的数据块总数。
一般情况下,Reduce的数目为(0.95或1.75)×(集群中的节点数×Tasktracker中Reduce任务的最小值)。若采用1.75云乘,可以得到比较好的负载均衡状态,因为若节点的速度较快,在完成第一轮Reduce任务后,可以马上开始第二轮。若用0.95的话,在Map任务一完成就马上启动所有Reduce任务,开始Map任务输出结果的传输。
如果在MapReduce框架中不需要进行归约操作,也可将Reduce任务的数目设置为零,此时Map任务所产生的输出结果会直接写入事先指定的输出路径,但在把这些结果写入文件系统前框架并不对结果进行排序。
② io.sort.mb (Map缓冲区大小,默认为100)当Map产生的数据非常大时,可以把io.sort.mb调大,那么Map在整个计算过程中spill(分割)的次数就会降低,Map任务的I/O操作就会变少,如果Map任务的瓶颈在磁盘上,这样的调整就会有效提高Map的计算性能。
③ io.sort.factor该参数表示当merge(合并)spill文件时,最多能有多少并行的数据流向merge文件中写入。如果Map产生的数据非常大,产生的spill文件大于10,而io.sort.factor的默认值是10,那么当Map计算完成做merge时,就没有办法一次将所有的spill文件merge成一个,而是会分多次,每次最多10个,即当Map的中间结果非常大时,高大此值,有利于减少merge次数,进而减少Map对磁盘的读写频率,有可以达到优化作业的目的。
附
io.sort.spill.percent 触发spill阈值百分比,默认值为0.8
io.sort.record.percent 记账缓冲区占Map缓冲区百分比,默认值为0.05
- 程序优化
通常情况下,MapReduce作业分产生大量的中间文件,若所需处理的原始数据量非常大,且在Map任务处理逻辑情况大到一定程序时,Map任务输出结果的中间文件会非常大,它是影响整个作业性能的一个重要因素。
针对上述问题,Hadoop中常通过修改Slave节点上的hadoop-site.xml配置文件中的MapReduce的本地目录配置选项,来提高MapReduce作业的吞吐率。另一个方法是将Map任务产生的中间文件进行压缩,即用空间换时间来提高MapReduce作业的性能。这种方法也有其缺点,如执行压缩算法会使得处理器的加载压力有所提高,但由于Reduce任务中Shuffle阶段能节省不少时间,总的来讲,对作业的性能还是有提高的。
目前,Hadoop支持的压缩格式有GzipCodec,LzoCodec,BZip2Codec、LzmaCodec等。通常来说,想要达到比较平衡的CPU和磁盘压缩比,LzoCodec压缩算法比较适合。
② 合理使用或编写自己的Combiner组合器当Map产生的数据很大时,会导致写入磁盘的数据量和通过网络传输到Reduce端的数据量增大,进而可能会影响到作业的性能。对此,MapReduce框架中提供了Combiner来减少中间结果对磁盘的写入和减少中间结果在Mapper和Reducer间的传输。
一般来讲,当MapReduce作业的算法中涉及一些分类的聚合或排序等操作时,就可以通过添加一个Combiner来减少Map与Reduce阶段之间Shuffle的数据量,减少网络流量,尽而缩短执行时间,提高作业的执行效率。
- 选用合适的数据类型来存储数据
MapReduce开发人员习惯使用Text类,但很多情况下并不是必要的。若过多采用Text对象处理非Text数据或结构较复杂的数据,则会导致占用CPU时间较长从而影响作业执行效率。因此,处理非文本数据时,要考虑使用更恰当的数据类型,比如IntWritable、FloatWritable等。
通常情况下,网络传输和磁盘I/O是MapReduce作业性能的瓶颈,如果中间数据存储采用二进制的writable类型会占用更少的空间,从而也起到节省磁盘、减轻网络等集群瓶颈的压力。同样,当处理整数类型时,使用VIntWritable或VLongWritable等变长数据类型在处理小整数数字时会节省更多的空间。
如果MapReduce作业仅仅是一系列作业中的一个,即使最后的输出需要使用文本化的数据,也可在中间结果或是中间作业的输出中使用SequenceFile保存中间结果,这样可节省网络传输,减低磁盘的I/O。
如果Hadoop自带数据类型不能满足需要,可以考虑编写自定义的数据类型。
- MapReduce的性能优化研究
- 优化调试算法,提高执行效率
- 优化配置参数,改进系统整体性能
- 减少I/O操作,提高执行效率
- 优化迭代算法,提高迭代性能
- 消除障碍同步,提高执行效率
- 优化连接算法,提高连接效率
- 影响性能指标的因素
- 数据初始化代价
- 中间数据代价
- 数据传输时间
- 调度时间



