作业运行后,许多开发人员可能会问:“能够让它运行得更快一些吗?"有一些Hadoop相关的“疑点”值得检查一下,看它们是不是引发性能问题的“元凶”。在开始任务级别的分析或优化之前,必须仔细研究下表所示的检查内容。
作业优化检查表:
范围 | 最佳实践 | 更多参考信息 |
mapper的数量 | mapper需要运行多长时间?如果平均只运行几秒钟,则可以看是否能用更少mapper 运行更长的时间,通常是一分钟左右。时间长度取决于使用的输人格式 | 输入分片与记录 |
reducer的数量 | 检查使用的reducer数目是不是超过1个。根据经验, Reduce任务应运行5分钟左右,且能生产出至少一个数据块的数据 | 默认的 MapReduce作业 |
combiner | 作业能否充分利用combiner来减少通过shuffle传输的数据量 | biner函数 |
中间值的压缩 | 对map输出进行压缩几乎总能使作业执行得更快 | 在MapReduce使用压缩 |
自定义序列 | 如果使用自定义的Writab1e对象或自定义的comparator,则必须确保已实现RawComparator | 实现定制的Writable集合 |
调整shuffle | MapReduce的shuffle过程可以对一些内存管理的参数进行调整,以弥补性能的不足 | 配置调优 |
分析任务
正如调试一样,对MapReduce这类分布式系统上运行的作业进行分析也有诸多挑战。Hadoop允许分析作业中的一部分任务,并且在每个任务完成时,把分析信息放到用户的机器上,以便日后使用标准分析工具进行分析。当然,对本地作业运行器中运行的作业进行分析可能稍微简单些。如果你有足够的数据运行map和reduce任务,那么对于提高mapper和reducer的性能有很大的帮助。但必须注意一些问题。本地作业运行器是一个与集群完全不同的环境,并且数据流模式也截然不同。如果MapReduce作业是1/0密集型的(很多作业都属于此类),那么优化代码的CPU性能是没有意义的。为了保证所有调整都是有效的,应该在实际集群上对比新老执行时间。这说起来容易做起来难,因为作业执行时间会随着与其他作业的资源争夺和调度器决定的任务顺序不同而发生改变。为了在这类情况下得到较短的作业执行时间,必须不断运行(改变代码或不改变代码),并检查是否有明显的改进。
有些问题(如内存溢出)只能在集群上重现,在这些情况下,必须能够在发生问题的地方进行分析。
1.HPROF分析工具
许多配置属性可以控制分析过程,这些属性也可以通过JobConf的简便方法获取。启用分析很简单,将属性mapreduce.task.profile设置为true即可:hadoop jar hadoop-examples.jar v4.MaxTemperatureDriver \
-conf conf/hadoop-cluster.xml \
-D mapreduce.task.profile=true \
input/ncdc/allmax-temp
上述命令正常运行作业,但是给用于启动节点管理器上的任务容器的Java命令增加了一个-agentlib参数。可以通过设置属性mapreduce.task.profile.params来精确地控制该新增参数。默认情况下使用HPROF,一个JDK自带的分析工具,虽然只有基本功能,但是能提供程序的CPU和堆使用情况等有价值的信息。
分析作业中的所有任务通常没有意义,因此,默认情况下,只有那些ID为0,1,2的map任务和reduee任务将被分析。可以通过设置mapreduce.task.profile.maps和mapreduce.task.profile.reduces两个属性来指定想要分析的任务ID的范围。
每个任务的分析输出和任务日志一起存放在节点管理器的本地日志目录的userlogs子目录下(和syslog,stdout,stderr)文件一起),可以根据日志聚合是否启用,使用hadoop日志章节介绍的方法获取到。