Hadoop的Shuffle过程

来源:互联网 发布:施温格 知乎 编辑:程序博客网 时间:2024/05/21 14:54

概述

为了让Reduce过程可以并行处理Map结果,必须对Map的输出进行一定的排序和分割,然后再交给对应的Reduce,而这个将Map输出进行进一步整理并交给Reduce的过程就成为了Shuffle。

总的来说,shuffle过程包含在Map和Reduce两端中。在Map端的shuffle过程是对Map的结果进行分区(partition),排序(sort)和溢写(spill),然后将属于同一个划分的输出合并在一起(merge)并写在磁盘上,同时按照不同的划分将结果发送给对应的Reduce。Reduce端又会将各个Map送来的属于同一划分的输出进行边合并(merge)边排序(sort),最后将具有相同key值的value聚合到同一组内,交由Reduce函数处理。


Map端

Map端的shuffle过程包含在collect函数对Map结果输出结果的处理过程中。Map函数的输出内存缓冲区是一个环状结构。

当输出内存缓冲区内容达到设定的阈值时,就需要把缓冲区内容溢写(spill)到磁盘中。但是在溢写的时候Map并不会阻止继续向缓冲区写入结果,如果Map结果生成速度比溢写速度快,那么缓冲区会写满,这时Map任务必须等待,直到溢写过程结束。

在collect函数中将缓冲区中的内容写出时会调用sortAndSpill函数。sortAndSpill函数每被调用调用一次就会创建一个spill文件,然后按照key值对需要写出的数据进行排序,最后按照划分的顺序将所有需要写出的结果写入这个spill文件中。如果用户作业配置了combiner类,那么在写出过程中会先调用combineAndSpill再写出,对结果进行进一步合并是为了让Map的输出数据更加紧凑。

最后在每个Map任务结束之后在Map的TaskTrack上还会执行合并操作,将Map生成的众多spill文件中的数据按照划分重新组织,以便于Reduce处理。主要是针对指定的分区,从众多个spill文件中拿出属于同一个分区的所有数据,然后将它们合并在一起,并写入一个已分区且已排序的Map输出文件中。

待唯一的已分区且已排序的Map输出文件写入最后一条记录后,Map端的shuffle阶段就结束了。下面就进入Reduce端的shuffle阶段。


Reduce端

在reduce端,shuffle阶段可以分成三个阶段:复制Map输出、排序合并和Reduce处理。

Map任务完成后,会通知父TaskTracker状态已更新,TaskTracker进而通知JobTracker。所以,对于指定作业来说,JobTracker能够记录Map输出和TaskTracker的映射关系。Reduce会定期向JobTracker获取Map的输出位置。一旦拿到输出位置,Reduce任务就会从这个输出对应的TaskTracker上复制输出到本地,而不会等到所有的Map任务结束。这就是Reduce任务的复制阶段。

在Reduce复制Map的输出结果的同时,Reduce任务就进入了合并阶段。这一阶段的主要任务是将从各个复制的Map输出文件进行整合,并维持数据的有序性。

当所有Map输出文件都已合并且保存有序后,就可以对合并的文件进行reduce处理了,具体是对key值进行比较,把具有相同key值的value聚合到同一组内,然后对组内的元素进行特定的reduce操作。


任务执行流程

  • 用户作业执行JobClient.runJob(conf)代码会在Hadoop集群上将其启动
  • 启动之后JobClient实例会向JobTracker获取JobId,而且客户端会将作业执行需要的作业资源复制到HDFS上,然后将作业提交给JobTracker
  • JobTracker在本地初始化作业,再从HDFS作业资源中获取作业输入的分割信息,根据这些信息JobTracker将作业分割成多个任务,然后分配给在与JobTracker心跳通信中请求任务的TaskTracker
  • TaskTracker接收到新的任务后会先从HDFS上获取作业资源,包括作业配置信息和本作业分片的输入,然后在本地启动一个JVM并执行任务
  • 任务结束之后将结果写回HDFS系统上
原创粉丝点击