对应用程序进行调优
由于mapreduce是迭代逐行解析数据文件的, 怎样在迭代的情况下, 编写高效率的应用程序, 是一种优化思路。
避免输入大量小文件。
大量的小文件(不足一个block大小)作为输入数据会产生很多的Map任务(默认一个分片对应一个Map任务), 而每个Map任务实际工作量又非常小, 系统要花更多的时间来将这些Map任务的输出进行整合。 如果将大量的小文件进行预处理合并成一个或几个大文件, 任务执行的效率可能会提升几十倍。
可手动将小文件合并成大文件, 或通过Hadoop的SequenceFile、CombineFileInputFormat 将多个文件打包到一个输入单元中, 使得每个Map处理更多的数据, 从而提高性能。
预判并过滤无用数据。
可以使用一些过滤工具, 在作业执行之前将数据中无用的数据进行过滤, 可极大提高MapReduce执行效率。 Bloom Filter 是一种功能强大的过滤器, 执行效率高, 时间复杂度为O(1), 缺点是存在一定的误判可能, 详细参考《Bloom Filter概念和原理》。
当将一个非常大的表和一个非常小的表进行表连接操作时, 可以使用Bloom Filter 将小表数据作为Bloom Filter的输入数据, 将大表的原始数据进行过滤(过滤不通过的数据一定是不可用的, 过滤通过的数据可能有用可能无用), 可提高程序执行的效率。
合理使用分布式缓存DistributedCache。
DistributedCache可以将一些字典、jar包、配置文件等缓存到需要执行map任务的节点中,避免map任务多次重复读取这些资源,尤其在join操作时,使用DistributedCache 缓存小表数据在map端进行join操作,可避免shuffle、reduce等操作,提高程序运行效率。
重用Writable类型。
避免大量多次new这些Writable对象,这会花费java垃圾收集器大量的清理工作,建议在map函数外定义这些Writable对象,如下所示:
class MyMapper … {
Text wordText = new Text();
IntWritable one = new IntWritable(1);
public void map(...) {
for (String word: words) {
wordText.set(word);
context.write(wordText, one);
}
}
}
合理设置Combiner。
Combine阶段处于Map端操作的最后一步,设置Combine操作可大大提高MapReduce的执行效率,前提是增加Combine不能改变最终的结果值,换句话说,不是所有的MapReduce程序都能添加Combine,如求平均数的MapReduce程序就不适合设置Combine操作。通常Combine函数与Reduce函数一致
外部文件引入
有些应用程序要使用外部文件, 如字典, 配置文件等, 这些文件需要在所有task之间共享, 可以放到分布式缓存DistributedCache中(或直接采用-files选项, 机制相同)。
使用StringBuffer而不是String
当需要对字符串进行操作时, 使用StringBuffer而不是String, String是read-only的, 如果对它进行修改, 会产生临时对象, 而StringBuffer是可修改的, 不会产生临时对象。
调试
最重要, 也是最基本的, 是要掌握MapReduce程序调试方法, 跟踪程序的瓶颈。 具体可参考:
http://www.cloudera.com/blog/2009/12/7-tips-for-improving-mapreduce-performance/
对参数进行调优(hadoop2.6.0-cdh-5.7.0)
当前hadoop系统有190多个配置参数, 怎样调整这些参数, 使hadoop作业运行尽可能的快, 也是一种优化思路。
参数调优的计算方法
调优三大原则
- 增大作业并行程度
dfs.blocksize=max(mapred.min.spilt.size,min(mapred.max.spilt.size,dfs.block.size))
- 给每个任务足够的资源
Map任务内存:mapreduce.map.memory.mb
Reduce任务内存:mapreduce.reduce.memory.mb
Map任务最大堆栈:mapreduce.map.java.opts.max.heap
Reduce任务最大堆栈:mapreduce.reduce.java.opts.max.heap
ApplicationMaster内存:yarn.app.mapreduce.am.resource.mb
- 在满足前两个条件下,尽可能地给shuffle(数据混洗-输入到输出整个过程)预留资源
最大洗牌连接:mapreduce.shuffle.max.connections
I/O排序内存缓存(MiB):mapreduce.task.io.sort.mb
I/O排序因子:mapreduce.task.io.sort.factor
洗牌期间并行传输的默认数量:mapreduce.reduce.shuffle.parallelcopies
压缩Map输出:mapreduce.map.output.compress
从系统实现角度进行优化
这种优化难度是最大的, 它是从hadoop实现机制角度, 发现当前Hadoop设计和实现上的缺点, 然后进行源码级地修改。该方法虽难度大, 但往往效果明显。