Hadoop之MapReduce的shuffle过程

目录

1.shuffle是什么?

2.shuffle做什么?

3.shuffle怎么做?


1.shuffle是什么?

shuffle是贯穿MapReduce中Map\Reduce阶段的一个操作,主要目的是为了把Map端的输出结果有效的传输到Reduce输入端

2.shuffle做什么?

  • 完整的将Map端的输出结果拉取到Reduce端
  • 在拉取数据的过程中,尽可能的减少网络传输的消耗
  • 尽可能的减少磁盘IO对Task执行效率的影响

3.shuffle怎么做?

(1)在Map端,shuffle分为四个步骤

  • split过程:对输入文件进行split切分操作,切片的策略如下:

InputSplit = max(minSize,min(maxSize,blockSize))

其中,在hadoop2.x下blockSize默认为128M,minSize和maxSize的值分别可以通过api设置

minSize:TextInputFormat.setMinInputSplitSize(job,1024L) 设置最小值为1KB

maxSize:TextInputFormat.setMaxInputSplitSize(job,1024*1024*10L) 设置最大值为10M

由此可以看出,split和block有如下关系:

a.当blockSize < maxSize && blockSize > minSize时,splitSize = blockSize(一对一)

b.当blockSize < maxSize && blockSize < minSize时,splitSize = minSize

c.当blockSize > maxSize && maxSize > minSize时,splitSize = maxSize(多对一)

所以一般情况下,split与block之间是一一对应的。

在文件大小保持不变,blockSize默认大小保持不变的情况下,有如下两种情况:

1.输入文件巨大,且都是大文件(注意:这里的大文件指的是文件大小均大于等于blockSize)

a.为了增加map Task的数量,只需要增大minSize的大小

2.输入文件巨大,且都是小文件(注意:这里的小文件指的是文件大小均小于blockSize)

  • partition过程:运行mapper之后得到的key/value的输出结果文件,但是这些结果文件不知道接下来要交给哪个reduce来处理,所以通过partition进行划分

MapReduce提供了partition接口,默认操作是对Key哈希后,再与reduce的数量取模,返回值决定该key/value由哪个reduce处理,这样的做法是为了防止数据倾斜,负载均衡

  • 写入缓冲区和溢写过程:在对map的输出结果进行partition后,会将map的输出结果和partition结果序列化后,一同写入内存缓冲区中。每一个map都有一个相应的内存缓冲区,该缓冲区默认大小为100M(mapreduce.task.io.sort.mb调整)。当内存缓冲区的占用率达到阈值时(mapreduce.map.io.sort.spill.percent,默认0.80,或者80%),会锁定着80%的内存,并将该内存内容溢写到磁盘中。

在将数据溢写到磁盘之前,会先对这80%的内容进行sort(先按照partition排序,再根据key字典排序),即将相同partition的数据归为一组,然后再对相同partition下的数据进行key的字典排序。

在此过程中,如果客户端自定义了Combiner(相当于mapReduce的reduce操作),会对同一partition下的同一个key的value进行合并,之后再溢写到磁盘中

与此同时,内存缓冲区剩余20%的空间会继续写入map输出结果,溢写过程和写入缓冲区过程两者之间互不影响

  • 归并过程:当输入的是一个大文件时,split之后每个map对应的split切片再经过溢写过程后会生成多个临时文件,这时候需要对溢写到磁盘的多个临时文件进行归并操作,合成一个已分区且已排序的大文件

这个过程中,又会对map输出结果进行一次sort排序(先按照partition排序,再根据key字典排序),与此同时,若客户端设置过Combiner,又会对同一partition下的同一个key的value进行合并。

当所有的临时文件都归并成一个大文件后,会删除所有的临时文件,并通知TaskTracker任务已完成,一旦有一个Map Task完成,Reduce Task就会通过Http复制Map Task的输出结果

合并Combiner和归并Merge的区别:两个键值对<"a",1>和<"a",1>,如果合并,会得到<"a",2>,如果归并,会得到<"a",<1,1>>

(2)在Reduce端,shuffle分为二个步骤

  • copy过程:通过Http方式获取map阶段的输出结果文件。

当Map Task完成后,会通知Map Task所在的TaskTracker状态已更新,然后TaskTracker会通过心跳机制向JobTracker汇报执行情况。所以一般情况下,JobTracker会有Map Task与TaskTracker的映射关系,reduce会定期向JobTracker获取Map Task的输出位置,一旦知道Map Task有输出结果,就会通过Map Task对应的TaskTracker复制结果文件。(并非需要等待所有的Map Task都执行完毕之后才开始copy数据,而是只要有就开始copy)

  • 写入缓冲区和merge sort过程:从Map端获取的输入文件会写入到内存缓冲区(该内存缓冲区不同于Map端的,使用的是Java Heap)

Copy过来的数据会先放入内存缓冲区中,如果内存缓冲区中能放得下这次数据的话就直接把数据写到内存中,即内存到内存

Reduce要向每个Map去拖取数据,在内存中每个Map对应一块数据,当内存缓存区中存储的Map数据占用空间达到一定程度的时候,开始启动内存中merge,把内存中的数据merge输出到磁盘上一个文件中,即内存到磁盘

在将buffer中多个map输出合并写入磁盘之前,如果设置了Combiner,则会化简压缩合并的map输出。Reduce的内存缓冲区可通过mapred.job.shuffle.input.buffer.percent配置,默认是JVM的heap size的70%。内存到磁盘merge的启动门限可以通过mapred.job.shuffle.merge.percent配置,默认是66%。

当属于该reducer的map输出全部拷贝完成,则会在reducer上生成多个文件(若拖取的所有map数据总量没有超过缓冲区的阈值,则数据就只存在于内存中),这时开始执行合并操作,即磁盘到磁盘

Map的输出数据已经是有序的,Merge进行一次合并排序(对key进行归并排序),所谓Reduce端的sort过程就是这个合并的过程。一般Reduce是一边copy一边sort,即copy和sort两个阶段是重叠而不是完全分开的。最终Reduce shuffle过程会输出一个整体有序的数据块,此时整个shuffle过程结束。

(3)对于Map端的输出结果和Reduce端的输出结果,都可以通过设置进行文件的压缩,从而减少网络传输的消耗

  • map的压缩输出

conf.setBoolean("mapred.compress.map.out", true);

conf.setClass(Job.MAP_OUTPUT_COMPRESS_CODEC, GzipCodec.class, CompressionCodec.class);

  • reduce的压缩输出

   conf.setBoolean("mapred.output.compress", true);

以上是我查阅许多博主对shuffle的理解后整理出来的,若有不对欢迎指正和探讨!

参考文献

MapReduce的shuffle过程详解

MapReduce shuffle过程详解

MapReduce:详解Shuffle过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值