MapReduce工作流程分析

从整体上,MapReduce框架可以分为五个不同实体:

  1. 客户端:提交 MapReduce job
  2. Yarn 资源管理器(ResouceManager):协调集群计算资源的分配。包含主要的组件:定时调用器(Scheduler)以及应用管理器(ApplicationManager)
    定时调度器(Scheduler):从本质上来说,定时调度器就是一种策略。当 Client 提交一个任务的时候,它会根据所需要的资源以及当前集群的资源状况进行分配。
    应用管理器(ApplicationManager):应用管理器就是负责管理 Client 用户提交的应用。监控应用的工作正是由应用管理器(ApplicationManager)完成的
  3. Yarn 节点管理器(NodeManager):启动和监视集群中每个节点的计算容器,并监控它们的资源使用情况(cpu,内存,磁盘及网络等),以及向 ResourceManager/Scheduler 提供这些资源使用报告
  4. Mapreduce 应用管理器(Application Master):负责调度Mapreduce任务。应用管理器和 MapReduce 任务是运行在容器中的,这个容器是由资源管理器分配的,并且接受阶段管理器的管理
  5. 分布式文件系统(通常为HDFS)

在这里插入图片描述
在这里插入图片描述

  1. 通过submit或者waitForCompletion提交作业,waitForCompletion()方法通过每秒循环轮转作业进度如果发现与上次报告有改变,则将进度报告发送到控制台
  2. 向ResourceManager申请Application ID,RM检查输入输出说明、计算输入分片
  3. 复制作业的资源文件,将作业信息(jar、配置文件、分片信息)复制到HDFS上用户的应用缓存目录中
  4. 通过submitApplication()方法提交作业到资源管理器
  5. 资源管理器在收到submitApplication()消息后,将请求传递给调度器(Scheduler)
    调度器为其分配一个容器Container,然后RM在NM的管理下在container中启动程序的ApplicationMaster进程
  6. ApplicationMaster对作业进行初始化,创建过个薄记对象以跟踪作业进度
    是一个java应用程序,他的主类是MRAppmaster
  7. ApplicationMaster接受来自HDFS在客户端计算的输入分片
    对每一个分片创建一个map任务,任务对象,由mapreduce.job.reduces属性设置reduce个数
  8. 如果作业不适合uber任务运行,ApplicationMaster就会为所有的map任务和reduce任务向资源管理器申请容器,请求为任务指定内存需求,map任务和reduce任务的默认都会申请1024MB的内存
  9. 资源管理器为任务分配了容器,ApplicationMaster就通过节点管理器启动容器。
    该任务由主类YarnChild的java应用程序执行。
  10. 运行任务之前,首先将资源本地化,包括作业配置、jar文件和所有来自分布式缓存的文件
  11. 最后执行Map任务和Reduce任务:

Map端流程

  1. 由程序内的InputFormat(默认实现类TextInputFormat)来读取外部数据,它会调用RecordReader(它的成员变量)的read()方法来读取,返回k,v键值对。map每次读取split的数据(一行一行的读取)
  2. 读取的k,v键值对传送给map()方法,作为其入参来执行用户定义的map逻辑
  3. context.write方法被调用时,outputCollector组件会将map()方法的输出结果写入到环形缓冲区内
  4. 环形缓冲区其实就是一个数组,后端不断接受数据的同时,前端数据不断被溢出,长度用完后读取的新数据再从前端开始覆盖
  5. spiller组件会从环形缓冲区溢出文件,这过程会按照定义的partitioner分区(默认是hashpartition),并且按照key.compareTo进行排序(快速排序、外部排序),若有combiner也会执行combiner。spiller的不断工作,会不断溢出许多小文件。这些文件仍在map task所处机器上
  6. 小文件执行merge(合并),行程分区且区内有序的大文件(归并排序,会再一次调用combiner)
  7. Reduce会根据自己的分区,去所有map task中,从文件读取对应的数据。

Reduce端流程
1.Copy过程。每个ReduceTask不断地通过RPC(HTTP协议)从ResourceManager获取MapTask是否完成信息。如果ReduceTask获知AppMaster上的MapTask执行完成,那么Shuffler的后半段过程开始启动。Reduce task通过网络向Map task获取某一分区的数据
8. Merge阶段。复制过来数据会先放到内存缓冲区中,当内存中的数据达到一定阈值时,就会启动内存到磁盘的Merge。与Map端类似,这也是溢写过程,会在磁盘中形成众多的溢写文件,由于一个split对应一个Map,Reduce端是从多个Map中拉取数据,所以也需要进行归并排序,成为一个有序的文件,最终每个相同的key分为一组执行一次Reduce方法
9. Reducer的输出文件。不断地进行Merge后,最后会生成一个“最终文件”。这个文件可能存放在磁盘,也可能存放在内存中,默认存放在磁盘上。当Reducer的输入文件已定时,整个Shuffle过程才最终结束

Shuffle中为什么用快速排序?

Hadoop Shuffle过程中总共发生3次排序,详细分别如下:

  • 第一次排序行为:在Map阶段,由环形缓冲区溢出到磁盘上时,落地磁盘的文件会按照key进行分区和排序,属于分区内有序,排序算法为快速排序
  • 第二次排序行为:在Map阶段,对溢出的文件进行combiner合并过程中,需要对溢出的小文件进行归档排序,合并,排序算法为归并排序
  • 第三次排序行为:在Map阶段,Reduce task将不同Map task端文件拉取到同一个Reduce分区后,对文件进行合并,排序,排序算法为归并排序

快速排序引人注目的三点:
【1】原地排序(只需要一个很小的辅助栈)
【2】 长度为N的数组排序所需要的时间和NlgN成正比
【3】 快排的内循环比其他大多数排序算法都要短小,这意味着无论是在理论还是实际中都要更快

快速排序和归并排序是互补的:
a、 归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将数组排序,而快速排序将数组排序的方式则是当两个子数组都有序时整个数组也就自然有序了
b、 归并排序递归调用发生在处理整个数组之前;快速排序递归调用发生在处理整个数组之后
c、 在归并排序中,一个数组被切分为两半;在快速排序中切分的位置取决于数组的内容

多路归并排序如何实现

  外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行多路归并排序。

处理过程
在这里插入图片描述
step1:分割+排序
从头开始将大文件File的一个小部分读入内存中,将这一小部分进行排序,然后将排序后的这一小部分写入到一个独立的小文件file1中。循环前面的步骤,生成了一堆内部有序的小文件file1、file2、file3、…、fileN
step2:多路归并
将每一个小文件的第一个数取出,即每一个小文件里的最小数,对这些数进行归并排序,将这些数里的最小数字numi(来自filei)写入大文件的第一行,此即整个大文件里的最小数字。将文件filei的行数指针+1,取出文件filei行数指针当前所指的数字,放入内存中,将大文件的行数指针+1。继续前面的循环,直到所有小文件都遍历完成。

发布了107 篇原创文章 · 获赞 19 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ThreeAspects/article/details/103605224