MapReduce源码分析二:ReduceTask执行流程

529 阅读3分钟

概述

ReduceTask是MapReduce程序reduce阶段执行的具体任务,同MapTask一样上层受MRAppMaster协调调度;内部基于ReduceContext管理各个组件。其主要功能包括:

  • 拉取Map阶段的输入 合并
  • 创建一个最终文件的迭代器
  • 执行自定义reduce逻辑
  • 输出

调用关系

程序入口:

org.apache.hadoop.mapred.YarnChild#main()

调用流程:

mr.png

核心类说明

YarnChild

入口类,通过其main()方法启动独立进程。内部主要是创建了reduce阶段的核心类ReduceTask,并调用起来其run(),真正开启reduce阶段的执行。

ReduceTask

reduce阶段的核心类,初始化基本组件与ReduceContextImpl环境上下文,并调用Reduce主逻辑,即run()。

Reduce

核心方法为run(),封装循环处理每条数据的完整流程,并基于模板方法让用于定义reduce()环节,扩展程序。

Shuffle操作的上下文:ShuffleConsumerPlugin.Context

Context封装Shuffle操作所依赖的各种基础组件,基础组件持有Context的引用,并通过Context来获取其他基础组件。这种方式,将组件之间的复杂依赖关系转化为对单一Context的依赖,从而实现组件之间的解耦。

总体来讲,使用Context封装组件的方式,一般有两大优点:

  • 外部与具体组件的通过Context解耦
  • 组件与组件之间通过Context解耦

ShuffleConsumerPlugin(具体实现类为Shuffle)

核心功能是通过一组Fetcher线程从Map端拉取数据,这个过程会根据数据量来决定将输出封装成InMemoryMapOutput还是OnDiskMapOutput,再通过commit()方法将封装的对象交给MergeManagerImpl来进行调度。

最终通过MergeManagerImpl#close()获取最终文件的迭代器。

ShuffleSchedulerImpl

Fetcher拉取完成,通过ShuffleSchedulerImpl#copySucceed()来提交给MergeManagerImpl管理。

ShuffleSchedulerImpl还有一个重要功能,就是接收map阶段任务完成的事件,进而解析事件为对应的数据结构并存储,供Fetcher线程操作。

Fetcher线程

功能为拉取map阶段的结果输出。默认会启动5个线程,并从ShuffleSchedulerImpl获取map的位置信息,然后进行拉取操作,拉取完成再调用ShuffleSchedulerImpl#copySucceed()通知ShuffleSchedulerImpl,来进行后续操作。

MergeManagerImpl

默认情况下,存储了Map阶段的两种输出即InMemoryMapOutput和OnDiskMapOutput的集合,并对应有两个线程来处理合并过程,分别是InMemoryMerger和OnDiskMerger。

InMemoryMerger合并会将结果写入文件,并再次交给MergeManagerImpl调度。 OnDiskMerger执行文件的合并,合并为新的文件。

close()方法执行最终的合并,即finalMerge(),会将内存、磁盘文件进行最终的合并,并返回迭代器。

Reducer

核心方法为run(),封装reduce阶段主要处理流程,并基于模板方法模式让用户定义reduce()环节,扩展程序。

核心代码:

public void run(Context context) throws IOException, InterruptedException {
    setup(context);
    try {
        while (context.nextKey()) {
            reduce(context.getCurrentKey(), context.getValues(), context);
            
            // If a back up store is used, reset it
            Iterator<VALUEIN> iter = context.getValues().iterator();
            if (iter instanceof ReduceContext.ValueIterator) {
                ((ReduceContext.ValueIterator<VALUEIN>) iter).resetBackupStore();
            }
        }
    } finally {
        cleanup(context);
    }
}

ReduceContextImpl

Reduce任务的上下文对象,封装其他组件的调用,提供统一入口。

LineRecordWriter

输出组件。