MapReduce中的mapper个数决定(很全)

对于大数据搬砖工来说,使用MapReduce调优是家常便饭,其中就必须知晓mapper和reducer个数的决定原理,参考了很多有关mapper个数的文章,大部分都非常零散,只讲其中一两点,下面是自己拼凑总结,并结合实际经验梳理的,供参考~


 

目录

1  因素一:文件压缩算法是否支持文件分片

2  因素二:选择的InputFormat类

2.1 HiveInputFormat类

方案一:确定map个数:参考:书《Hive性能调优实战》

方案二:确定splitsize来确定map数 

2.2 CombineHiveInputFormat类

1)由以下四个参数影响

2)具体CombineHiveInputFormat类切片算法逻辑

3)具体的参数优先级(从小到大)

3  需要调整mapper个数的场景:

3.1 每一个mapper处理的数据量不均匀

1)长尾任务:某几个mapper的latency超过平均mapper的latency的2倍

2)大量小文件

情况一:来自数据源输入的小文件

情况二:MR输出的小文件,如reduce过程中产生的小文件,通过日志可以看到

3.2 数据量较大,分配到每个mapper任务处理的数据量也很大,单个mapper任务执行时间长


注:

1)对mappersplit切片:逻辑切片;对block的切片:物理切片

2)为什么默认map的split大小是hdfs中的块大小128MB呢?

        在集群中,数据被分割成多个block存在hdfs中不同的datanode上,而当一个MR任务对数据处理时,先要从datanode上获取所需数据块,而当这个MR任务的split大小刚好等于文件块大小时,直接访问本地的datanode节点,来扫描hdfs文件块,减少跨节点的文件扫描,减少网络IO

即当逻辑切片大小 = 物理切片大小,一般情况下最优

3)并行度 = 个数

4)实际 mapper个数调优需多次验证决定

  • mapper个数太多:太多的资源读取、磁盘io、网络Io、每个task创建和退出费时
  • mapper个数太少:不能充分利用资源,每个mapper处理的数据量过大,费时

 

例子:两张表join

  • 大表总共158749566行,文件总大小4.4G,存储个数22个文件,每个大小200Mb左右。
  • 小表总共1979375 行,文件大小50.7Mb,存储个数2个文件,大小50Mb以内。

1  因素一:文件压缩算法是否支持文件分片

  • 在map阶段,会先进入InputFormat判断:
  • InputFormat类,用于对MapReduce作业输入的处理,InputFormat涉及3个接口/类,即InputFormat、InputSplit和RecordReader。
  • 分别用来获取文件的逻辑切片,按照切片指定输入到一个个map;获取分片大小、将数据转化为kv值
  • 其中下列的文件压缩算法不支持文件切片,此时一个map任务处理的数据量会>=每个文件的大小

例子:当压缩方式为deflate时:

使用不同参数执行上面代码产生的map---------------------------------
--1.
使用系统配置的默认值
set mapred.max.split.size  = 256000000; --
set mapred.min.split.size = 256000000;
Hadoop job information for Stage-1: number of mappers: 24; number of reducers: 17

--2.降低系统默认值
set mapred.max.split.size=134217728;
set mapred.min.split.size=134217728;
Hadoop job information for Stage-1: number of mappers: 24; number of reducers: 17

--3.调高系统默认值
set mapred.max.split.size=500000000;
set mapred.min.split.size=256000000;
Hadoop job information for Stage-1: number of mappers: 9; number of reducers: 17

--4.调高系统默认值
set mapred.max.split.size=1024000000;
set mapred.min.split.size=1024000000;
Hadoop job information for Stage-1: number of mappers:6 ; number of reducers: 17

  • 发现:当降低splitsize参数值,本应增加map的个数,但是实际的map数量没变,而调高splitsize参数值时,本应减少map个数,实际上也减少了。
  • 因为此时不支持对文件切分(即逻辑切分),map处理的数据量必须大于等于文件的大小,所以调低参数<文件大小时,也没用,而如果增大splitsize,相当于增大了一个map处理的数据量。
  • 因为deflate压缩算法虽然不支持文件切分,但是可以进行文件合并。而从hive0.5开始就默认map前进行小文件合并了(默认的InputFormat类是CombineHiveInputFormat)

2  因素二:选择的InputFormat类

  • HiveInputFormat类和CombineHiveInputFormat类都是继承自InputFormat类,但是从hive0.5开始默认是CombineHiveInputFormat类
  • 不同的类,决定mapper个数的参数不一样,但都要从两方面来考虑:参数、参数优先级

2.1 HiveInputFormat类

注:

  • 使用 HiveInputFormat类的企业已经很少
  • 优先用方案一,方案二是方案一的简化。
方案一:确定map个数:参考:书《Hive性能调优实战》

首先取:max{defaultNum,mapred.map.tasks} 作为后续比较的备选

  • 理解:
    • 对文件的分块:物理切片;对input的数据切片:逻辑切片;defaultNum是当物理切片大小 = 逻辑切片大小时的map数量,此时两者完全匹配,减少了网络io和磁盘io,一般情况下,性能最优
    • 只有当用户指定的期望的Map大小大于defaultNum时,才会发挥出所设置的map个数参数的效果,若是小于defaultNum,则每个mapper处理的数据量都不饱和,资源浪费,都不能达到一般情况下的性能最优,所设置的参数不起作用
    • defaultNum:默认情况下Map的个数defaultNum=目标文件或数据的总大小totalSize/hdfs集群文件块的大小blockSize

其次分片大小取:max{mapred.min.split.size, blockSize} ,则个数取min{totalsize/mapred.min.split.size,totalsize/blockSize}

  • 理解当设置的mapred.min.split.size参数小于blockSize时,参数不起作用,因为一般的切片大小就为blockSize,当大于blockSize时这个参数才会有效

最后取min{max{defaultNum,mapred.map.tasks} , min{totalsize/mapred.min.split.size,totalsize/blockSize}}

即上面两个的较小值,即满足各种参数设置下的最小map数

方案二:确定splitsize来确定map数 

 参考:CSDN上的大多文章 :

真正让你明白Hive参数调优系列1:控制map个数与性能调优参数 (taodudu.cc)

hive如何调整map数和reduce数 - 简书 (jianshu.com)

(36条消息) Hive 如何确定 map 数的?_hive如何判断map个数_xinxindsj的博客-CSDN博客

(35条消息) hive执行时map任务数的确定_hive执行的job数是怎么确定的_大数据男的博客-CSDN博客

按照上面的理解:

首先取:min{goalSize,blockSize} 

  • goalSize:totalSize/mapred.map.tasks
  • 其实就相当于方案一的:max{defaultNum,mapred.map.tasks}

最后取:splitSize = max{mapred.min.split.size,min{goalSize,blockSize}}

  • 相比于方案一,少了mapred.min.split.size和blocksize的比较,因为这个时候一般map的splitsize小于等于blocksize(128Mb)

总结:按照HiveInputFormat类,mapper数量=min{max{defaultNummapred.map.tasks} , min{totalsize/mapred.min.split.size,totalsize/blockSize}} 决定mapper数量的外来参数只有mapred.map.tasks与mapred.min.split.size,当需要增加mapper数时,变大mapred.map.tasks或者变小mapred.min.split.size

2.2 CombineHiveInputFormat类

区别:CombineHiveInputFormat类相较 HiveInputFormat类自动实现对hdfs小文件的合并

map个数的计算:

1)由以下四个参数影响
  • mapred.min.split.size 或者 mapreduce.input.fileinputformat.split.minsize(Hadoop2.0版本后这个参数的名字)
  • mapred.max.split.size或者mapreduce.input.fileinputformat.split.maxsize
  • mapred.min.split.size.per.rack
  • mapred.min.split.size.per.node

还要与配置文件中的集群中可用mapper数量比较

2)具体CombineHiveInputFormat类切片算法逻辑

以下参考:(35条消息) hive执行时map任务数的确定_hive执行的job数是怎么确定的_大数据男的博客-CSDN博客

假设集群有3个机架,一共6个节点,9个block,假设每个block的大小都是100M。

设置合并后的最大分片为244M

set mapreduce.input.fileinputformat.split.maxsize=256000000;

设置一个节点上最小的分片大小,这个值设的不一样会影响分片数量。

set mapred.min.split.size.per.node=256000000;

设置 一个机架上最小的split大小,这个值设的不一样会影响分片数量。

set mapred.min.split.size.per.rack=256000000;

算法过程:

简单记:先从小范围(node)的小文件(文件大小<mapred.min.split.size.per.node)开始合并,如果还有剩余的,就在这几个节点(rack)的大范围再次合并小文件,如果还有剩余,在几个rack间再次合并。

  • 节点内部

先从节点内部开始循环,机架1上node1三个分片之和为300M > 244M(设置的mapred.min.split.size.per.node一个节点最小的切片大小为244m),即A、B、C会合并为一个分片;

node2上只有一个block,大小是100M,小于节点最小分片大小,会暂时保留;node3和node2一样;

node4上有两个block,不够组成一个大分片;

  • 同一个机架的节点间

从node2的block和node4的两个block,即G/H/F会拼成一个大分片;

机架1上node3上的block F会暂时保留;

  • 机架间的合并

机架1上的F和机架2的I以及机架3上的H会组成一个大的分片;

3)具体的参数优先级(从小到大)

max.split.size <= min.split.size <= min.size.per.rack <= min.size.per.node

当四个参数设置矛盾时,系统会自动以优先级最高的参数为准,进行计算,如上面的算法说明中,mapreduce.input.fileinputformat.split.maxsize=256000000设置和 min.size.per.node一样,但是在实际中还是会将300M的合为一个分片。

注:

  • 四个参数的配置大小一般满足:

max.split.size >= min.split.size >= min.size.per.rack >= min.size.per.node

  • 在上面这个例子中mapper的个数与参数mapred.map.tasks基本无关,取上面四个参数得出的mapper数与集群中可用mapper数的较小值。

3  需要调整mapper个数的场景:

3.1 每一个mapper处理的数据量不均匀
1)长尾任务:某几个mapper的latency超过平均mapper的latency的2倍
  • 解决:
    • mapred.min.split.size
    • mapred.max.split.size
2)大量小文件

(使用默认参数的,及默认输入格式FileInputFormat的MR会为每一个小文件都生成一个切片,浪费计算资源)

  • 情况一:来自数据源输入的小文件
    • 解决:使用CombineHiveInputFormat类,来合并一个DataNode上的小文件
      • mapred.max.split.size限制合并文件数
      • mapred.min.split.size.per.node决定这个node上的文件是否需要合并
      • mapred.min.split.size.per.rack决定这个rack上的文件是否需要合并
  • 情况二:MR输出的小文件,如reduce过程中产生的小文件,通过日志可以看到
    • 解决:
      • set hive.merge.mapfiles=true;    默认值ture,在Map-only的任务结束时合并小文件
      • set hive.merge.mapredfiles=true;    默认值false,在Map-Reduce的任务结束时合并小文件
      • set hive.merge.size.per.task=256000000;    默认值256M((把处理小文件的几个mapper合成一个mapper)
      • set hive.merge.smallfiles.avgsize=16000000

(默认值16M,当输出文件的平均大小小于16M时,启动一个独立的map-reduce任务进行文件merge)

3.2 数据量较大,分配到每个mapper任务处理的数据量也很大,单个mapper任务执行时间长
  • 解决:
    • 调整mapper数,是增加还是减少验证来看哪个快,有时太多的mapper,会增加启动和退出及落盘的时间
    • splitSize = max{mapred.min.split.size,min{goalSize,blockSize}}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值