彻底解惑MapReduce核心shuffle的执行流程及MapReducer调优

 以处理text文件为例

map端

map端:
    1、MRApplicationMaster启动maptask,并分配其一个编号,maptask根据编号寻找对应的存储文件位
       置信息及切片长度的数据切片,默认数据切片对应的文件大小与blocksize大小一致。然后maptask
       再根据数据切片寻找对应数据文件信息。然后maptask会通
       org.apache.hadoop.mapreduce.InputFormat接口的TextInputFormat实现类的
       createRecordReader()方法创建LineRecordReader对象,通过该对象的nextKey()和
       nextValue()方法从hdfs上逐行读取数据文件内容,key为该行数据的偏移量,value为该行数据。
       再交由mapper类进行数据的处理。
       
    2、mapper类对数据处理完后会调用Context对象的write()方法将数据写出,而
       org.apache.hadoop.mapred.OutputCollector类则负责将这些数据收集放入环形缓冲区中。数据    
       进入缓冲区前会通过org.apache.hadoop.mapred.Partitioner类进行分区,分区方式为对key取
       hash再对reduce数量取模。这就使得一个分区对应于一个reducetask。分区之后数据文件文件会序  
       列化成字节数组,进入环形缓冲区中。每个maptask都有一个环形缓冲区,默认大小为100MB,环形缓
       冲区本质上就是一个字节数组。

    3、当环形缓冲区达到80%满的时候,启动一个单独的Spiller线程锁定环形缓冲区这80%的内存,进行溢
       写操作,其余20%的内存仍然可以接收数据的输入。每次溢写被执行后,都会形成一个小文件,当数据
       写入影响到了溢写时,环形缓冲区的数据输入会阻塞。在溢写真正被触发执行前,会先通过
       org.apache.hadoop.util.QuickSort类先对环形缓冲区中的数据进行一个二次快速排序,先按分
       区排,再按key排,排序结束后单个分区内数据按key有序。

    4-a、如果设定了combiner,并且当前maptask已经溢写形成的小文件数目不小于3,则触发combiner,     
         combiner会对环形缓冲区内的数据做一次按key聚合操作,减少溢写到磁盘的数据量(不改变溢写的
         总文件数,这点要理解)。每一次溢写都是按分区号逐个进行的,溢写操作会直到最后一份数据溢写
         完成后结束。
    5-a、整个maptask的所有溢写操作完成后会对当前maptask溢写产生的所有小文件执行merge操作,将其
         merge成一个大的数据文件和索引文件。整个merge过程用到了外部排序和归并排序两种排序算法,
         merge结束,该数据文件内每个分区内的数据都有序排列。然后删除所有spill中间文件后,
         当前maptask结束。
         
    4-b、如果设定了combiner,并且当前maptask溢写形成的小文件数目小于3,则直接执行溢写操作,溢
         写按分区号逐个进行,溢写操作会直到最后一份数据溢写完成后结束。
    5-b、整个maptask的所有溢写操作完成后会对当前maptask溢写产生的所有小文件执行merge操作,将其
         merge成一个大的数据文件和索引文件。整个merge过程用到了外部排序和归并排序两种排序算法,
         merge结束,该数据文件内每个分区内的数据都有序排列。然后删除所有spill中间文件后进入
         combiner阶段,combiner会对数据文件内的每一个分区数据做一次按key聚合操作,减少输入到
         reduce端的数据量。combiner完成则当前maptask结束。


注意事项:
    merge前,A小文件的1号分区有{a:2},B小文件的1号分区有{a:5},merge之后就成了C大文件1号分区{a:[2,5]}。
    merge不是一蹴而就的,每次只merge10个文件,由mapreduce.task.io.sort.factor控制。
    combiner前,A小文件的1号分区有{a:1},{a:4},B小文件的1号分区有{b:1},{b:3},combiner之后就形成了A小文件的1号分区有{a:5},B小文件的1号分区有{b:4}。

####以上注意事项请好好理解

####集群很繁忙的情况下设置了combiner,也可能不生效。
#####所有溢写小文件和merge后的大文件都是senquence文件

 reduce端

reduce端:
    1、MRApplicationMaster启动reducetask,并给其分配一个编号,reducetask根据编号通过http协
       议拉取对应的分区数据,该分区数据可能位于所有的maptask中,所以reducetask会启动多个线程拉
       取数据,最多5个,由参数mapreduce.reduce.shuffle.parallelcopies控制。每一个
       reducetask都有一个内存缓冲区,当在某个map端拉取的数据大小小于内存缓冲区大小的25%,则进
       入内存缓冲区中,否则直接进入磁盘。
    
    2、当内存缓冲区的数据文件达到1000个(mapreduce.reduce.merge.inmem.threshold)或者内存缓冲
       区的数据占用内存比达到66%(mapreduce.reduce.shuffle.merge.percent)的时候,会在内存中
       执行merge操作。如果设定了combiner,则merge过程中也会执行combiner操作,这两个操作结束,
       内存缓冲区中的数据溢写到磁盘形成小文件,溢写的次数可能很多次,且有一些maptask拉取过来的文
       件不经过内存缓冲区直接存在磁盘,所以磁盘上的小文件可能有很多个。由由于merge过程会使用归并
       排序,所以单个溢写小文件中的数据也是有序排列的。
    
    3、当当前reducetask的所有数据全部拉取并在磁盘形成小文件后,会将所有的小文件merge成一个大文
       件,merge过程会使用归并排序,所以形成的大文件也是有序的。整个merge过程不是一蹴而就的,每
       次merge只会合并10个文件,由mapreduce.task.io.sort.factor控制,假设有50个文件,则要执
       行6次merge。
    

    4、merge之后Reducer类通过迭代器获取数据的key-value键值对,知道一个key对应的所有键值对全部    
       获取玩会执行reduce方法处理,处理结束通过Context对象的write方法将处理结果写出,但它并非
       直接写出,而是会判断配置文件中配置的输出文件类型后再写出,如果没有配置,则reducetask会
       通过org.apache.hadoop.mapreduce.InputFormat接口的TextInputFormat实现类的
       getRecordWriter()方法创建LineRecordWriter对象,通过该对象的write()方法将该key对应
       数据写出到hdfs的结果文件中。则然后处理下一个key对应的数据,直到当前reducetask的所有数据
       全部被处理完成且正确输出后,当前reducetask结束。
        
        #####输出到hdfs上时,每一对key-value对应一行数据,tab键分隔。
        #####如果当前reducetask的编号为0,则产生的输出文件就为part-r-000000,为1,则产生的输出文件就为part-r-000001
        #####过程中涉及到两次merge,这种情况发生在maptask特别多的情况下。在极少maptask的情况下,设甚至是可以没有merge的。





#####所有溢写小文件和merge后的大文件都是senquence文件

hadoop调优

1、Mapper阶段
    减少溢写次数:
            参数:io.sort.mb     io.spill.percent
    减少merge次数:
            参数:io.sort.factor
    开启combiner:
            在不影响业务的情况下。
2、Reducer阶段
    合理设置mapper和reducer数:
        mapper数量取决于切片大小和文件大小,切片大小不好改变,文件大小也不好改变。
        reducer数则可以按照需要设置,我们可以设置每个reducer处理的数据量多大。
    设置maper和reducer共存,让reducer提前运行:
        参数:mapreduce.job.reduce.slowstart.completedmaps	默认0.05

3、在各阶段合理配置压缩
    map输入:bzip2/lzo     要支持分割
    map输出:lz4           压缩解压缩时间段
    map输出:
        最终输出:bzip4    体积小
        非最终输出:bzip2/lzo   要支持分割
    参考:
        https://blog.csdn.net/pengzonglu7292/article/details/79419021

其他的调优就调不了了,应该在hive中调。




     
 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二百四十九先森

你的打赏是我努力的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值