MapReduce的优化方法:
从以下6个方面着手考虑:
1、数据输入
map端数据输入时主要需要考虑的是小文件(因为hadoop默认的切片原则是按文件进行的)的问题:
针对小文件的问题我们有如下两种解决方案:
(1)合并小文件:在map读取数据任务开始前,可以人工的对小文件进行一个合并,合并成一个大文件。
(2)采用CombineTextInputFormat的方式读取文件。
关于该机制的介绍如下:
hadoop框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
虚拟存储切片最大值设置
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。
切片机制
生成切片过程包括:虚拟存储过程和切片过程二部分。
自我总结:
先有一个虚拟存储过程,并不是真正的切块。
在虚拟存错过程中,分为如下情况:
1、当一个文件的大小大于两倍所设置的最大的切片大小时setMaxInputSplitSize,先在逻辑上切分出设置的最大的分片大小,然后对剩余大小的块在进行判断
While(flag){
If(是否大于两倍) {执行(先切分出最大的分片大小为一块,然后对剩余的文件大小在进行判断)}
If(是否大于一倍小于两倍) {执行(将文件均分成两个虚拟存储块,不在循环判断)}
If(是否小于一倍) {执行(直接划分一块,不在进行循环判断)}
}
2、在虚拟存储之后,进行真正的切片过程:
While(对每一个虚拟存储过程后形成的块进行循环判断){
If(块的大小是否大于等于所设置的最大块的大小setMaxInputSplitSize){
大于的话执行{单独形成一个切片}
}else(不大于的话){
执行{把当前块和下一个块进行合并,若是大于setMaxInputSplitSize则形成一个切片,若是不大于则和下一个进行合并判断是否大于setMaxInputSplitSize,一直合并下去,直到合并后的文件大于等于setMaxInputSplitSize,之后会形成一个切片。 }
}
}
2、Map阶段
map阶段的优化主要从以下三个方面:
3、Reduce阶段
reduce阶段的优化主要从以下四个方面:
4、I/O传输
I/O传输过程中的优化从以下两个方面考虑:
其中第一个方面是我上个博客中所讲述的压缩方式的比较和选择。
< https://blog.csdn.net/zuixue_lei/article/details/108185415>
5、数据倾斜方面
数据倾斜问题:
个人理解:数据倾斜通常是分区不恰当造成的,因为一个reduceTask负责处理一个分区的任务,当数据分布不均时,可能有些分区中有很多的数据,另一些分区中的数据极少,这就造成了某一个或介个reduceTask处理的数据过多了。
数据倾斜问题的解决:
6、常用的调优参数
(1)资源相关参数
以下参数是在用户自己的MR应用程序中配置就可以生效。
配置参数 | 参数说明 |
---|---|
mapreduce.map.memory.mb | 一个MapTask可使用的资源上限(单位:MB),默认为1024。如果MapTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.reduce.memory.mb | 一个ReduceTask可使用的资源上限(单位:MB),默认为1024。如果ReduceTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.map.cpu.vcores | 每个MapTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.cpu.vcores | 每个ReduceTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.shuffle.parallelcopies | 每个Reduce去Map中取数据的并行数。默认值是5 |
mapreduce.reduce.shuffle.merge.percent | Buffer中的数据达到多少比例开始写入磁盘。默认值0.66 |
mapreduce.reduce.shuffle.input.buffer.percent | Buffer大小占Reduce可用内存的比例。默认值0.7 |
mapreduce.reduce.input.buffer.percent | 指定多少比例的内存用来存放Buffer中的数据,默认值是0.0 |
以下的 应该在YARN启动之前就配置在服务器的配置文件中才能生效(yarn-default.xml)
配置参数 | 参数说明 |
---|---|
yarn.scheduler.minimum-allocation-mb | 给应用程序Container分配的最小内存,默认值:1024 |
yarn.scheduler.maximum-allocation-mb | 给应用程序Container分配的最大内存,默认值:8192 |
yarn.scheduler.minimum-allocation-vcores | 每个Container申请的最小CPU核数,默认值:1 |
yarn.scheduler.maximum-allocation-vcores | 每个Container申请的最大CPU核数,默认值:32 |
yarn.nodemanager.resource.memory-mb | 给Containers分配的最大物理内存,默认值:8192 |
Shuffle性能优化的关键参数,应在YARN启动之前就配置好(mapred-default.xml)
配置参数 | 参数说明 |
---|---|
mapreduce.task.io.sort.mb | Shuffle的环形缓冲区大小,默认100m |
mapreduce.map.sort.spill.percent | 环形缓冲区溢出的阈值,默认80% |
(2)容错相关参数(MapReduce性能优化)
配置参数 | 参数说明 |
---|---|
mapreduce.map.maxattempts | 每个Map Task最大重试次数,一旦重试次数超过该值,则认为Map Task运行失败,默认值:4。 |
mapreduce.reduce.maxattempts | 每个Reduce Task最大重试次数,一旦重试次数超过该值,则认为Map Task运行失败,默认值:4。 |
mapreduce.task.timeout | Task超时时间,经常需要设置的一个参数,该参数表达的意思为:如果一个Task在一定时间内没有任何进入,即不会读取新的数据,也没有输出数据,则认为该Task处于Block状态,可能是卡住了,也许永远会卡住,为了防止因为用户程序永远Block住不退出,则强制设置了一个该超时时间(单位毫秒),默认是600000(10分钟)。如果你的程序对每条输入数据的处理时间过长(比如会访问数据库,通过网络拉取数据等),建议将该参数调大,该参数过小常出现的错误提示是:“AttemptID:attempt_14267829456721_123456_m_000224_0 Timed out after 300 secsContainer killed by the ApplicationMaster.”。 |