运行机制
调用Job的submit()方法运行MapReduce作业,也可以调用waitForCompletion(),它用于提交以前没有提交的作业并等待它的完成。
- 客户端,提交MapReduce程序
- YARN资源管理器,负责协调集群上计算机资源的分配
- YARN节点管理器,负责启动和监视集群中及其上的计算容器
- MapReduce的application master,负责协调运行MapReduce作业的任务。它和MapReduce任务在容器中运行,这些容器由资源管理器分配并由结点管理器进行管理。
- 分布式文件系统,用来与其他实体间共享作业文件。
作业的提交
Job的submit()方法创建一个内部的JobSummiter实例,并调用submitJobInternal()方法。提交作业后,waitForCompletion()轮询作业进度。
JobSummiter(client)实现作业提交过程:
- 向资源管理器请求一个新应用ID,用于MapReduce作业ID
- 检查作业输出说明,即检查有无输出目录或输出目录是否已经存在
- 计算作业的输入分片
- 将运行作业所需要的资源(作业JAR文件,配置文件,计算所得的输入分片)复制到共享文件系统中的一个以作业ID命名的目录下。
- 调用资源管理器的submitApplication()方法提交作业
作业的初始化
资源管理器收到调用它的submitApplication()消息后,将请求传递给YARN调度器。调度器分配一个容器,然后节点管理器在资源管理器的管理下在容器中启动applicationmaster的进程。
ApplicationMaster保持对作业进度跟踪。其接收来自共享文件系统的输入分片,然后对每一个分片创建一个Map任务以及多个Reduce任务对象,任务ID分配。最后调用setupJob()方法设置OutputCommiter。
任务分配
当任务运行小于新的容器分配和运行任务开销时,不需要申请容器。
当需要申请容器时,application master会为该作业中所有的map和reduce任务向资源管理器请求容器,通过心跳机制传输请求。通常情况下,当启动容器处理HDFS数据块时(map任务),应用会向如下顺序(失败进行下一个,成功结束)节点申请容器:(数据本地化)
- 存储该数据块的三个复本的节点
- 存储这些复本的机架中的一个节点
- 申请集群中的任意节点
任务执行
分配完容器后,application master通过与节点管理器通信启动容器。任务由主类为YarnChild(在指定的JVM中运行)的一个java应用程序执行。运行任务之前,首先将任务需要的资源本地化,包括作业配置,JAR文件和所有来自分布式缓存的文件。然后再执行任务。
进度和状态更新
一个作业和它的每个任务都有一个状态(status),包括:作业或任务的状态(运行中,成功完成,失败),map和reduce进度,作业计数器的值,状态消息或描述。
任务通过umbilical接口向自己的application master报告进度和状态(每隔3秒)。
客户端定时轮询一次application master以接收最新的状态。
作业完成
任务完成时,application master和任务容器清理其工作状态,作业信息由作业历史服务器存档。
shuffle和排序
MapReduce确保每个reducer的输入都是按键排序的。系统执行排序,将map输出作为输入传递给reducer的过程称为shuffle。
map端
每个map任务有一个环形内存缓冲区,默认大小100M。
- 首先根据设计的分区将数据划分成相应的分区
- 当缓冲区内容达到阈值(默认0.8),将内容溢出(spill)到磁盘
- 在内存中按键进行排序
- 如果有combiner函数,则在该文件上合并数据
- 建立一个spill文件,将内容溢出到该文件中
- map写完数据后,有多个溢出文件,则将溢出文件合并成一个已分区已排序的输出文件
- 当至少有3个spill文件时,则combiner在该分区上合并数据
reduce端
reducer通过HTTP得到输出文件的分区
- 如果map输出较小,会被复制到reduce任务JVM内存中
- 如果map输出较大,则复制到磁盘中
- 当内存缓冲区达到阈值大小或达到map输出阈值,合并后溢出到磁盘,可执行combiner
- 复制完所有map输出后,reduce任务进入排序阶段,合并map输出,维持其顺序排序