1.数据输入阶段 大量小文件的输入时,使用combineTextinputformat,用法为: job.setInputFormatClass(CombineTextInputFormat.class); CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m 2. Map 阶段 1) 减少溢写(spill)次数:通过调整 io.sort.mb 及 sort.spill.percent 参数值,增大触发 spill 的内存上限,减少 spill 次数,从而减少磁盘 IO。 2) 减少合并(merge)次数:通过调整 io.sort.factor 参数,增大 merge 的文件数目,减少 merge 的次数,从而缩短 mr 处理时间。 3) 在 map 之后,不影响业务逻辑前提下,先进行 combine 处理,减少 I/O。 3. Reduce 阶段 1) 合理设置 map 和 reduce 数:两个都不能设置太少,也不能设置太多。太少,会导 致 task 等待,延长处理时间;太多,会导致 map、reduce 任务间竞争资源,造成处理超时等错误。 2) 设置 map、reduce 共存:调整 slowstart.completedmaps 参数,使 map 运行到一定程 度后,reduce 也开始运行,减少reduce 的等待时间。 3) 规避使用 reduce:因为 reduce 在用于连接数据集的时候将会产生大量的网络消耗。 4) 合理设置 reduce 端的 buffer:默认情况下,数据达到一个阈值的时候,buffer 中的数据就会写入磁盘,然后 reduce 会从磁盘中获得所有的数据。也就是说,buffer 和 reduce 是没有直接关联的,中间多个一个写磁盘->读磁盘的过程,既然有这个弊端,那么就可以通过参数来配置,使得 buffer 中的一部分数据可以直接输送到 reduce从而减IO 开销: mapred.job.reduce.input.buffer.percent,默认为 0.0。当值大于 0 的时候,会保留指定比例的 内存读 buffer 中的数据直接拿给 reduce 使用。这样一来,设置 buffer 需要内存,读取数据需 要内存,reduce 计算也要内存,所以要根据作业的运行情况进行调整。 4. IO 传输 1) 采用数据压缩的方式,减少网络 IO 的的时间。安装 Snappy 和 LZO 压缩编码器。 2)使用 SequenceFile 二进制文件。 5. 数据倾斜问题 1)自定义分区 2)使用combine进行聚合操作,精简数据 3)使用mapjoin避免使用reducejoin 6.HDFS上小文件处理: 1) Hadoop Archive: 是一个高效地将小文件放入 HDFS 块中的文件存档工具,它能够将多个小文件打包成一个 HAR 文件,这样就减少了 namenode 的内存使用。 2) Sequence file: sequence file 由一系列的二进制 key/value 组成,如果 key 为文件名,value 为文件内容, 则可以将大批小文件合并成一个大文件。 3) CombineFileInputFormat: CombineFileInputFormat 是一种新的 inputformat,用于将多个文件合并成一个单独的 split,另外,它会考虑数据的存储位置。 4)开启JVM 重用 对于大量小文件Job,可以开启JVM 重用会减少 45%运行时间。 JVM 重用理解:一个 map 运行一个 jvm,重用的话,在一个 map 在 jvm 上运行完毕后, jvm 继续运行其他 map。 具体设置:mapreduce.job.jvm.numtasks 值在 10-20 之间。