Hadoop2.6.0运行mapreduce之推断(speculative)执行(上)

前言

当一个应用向YARN集群提交作业后,此作业的多个任务由于负载不均衡、资源分布不均等原因都会导致各个任务运行完成的时间不一致,甚至会出现一个任务明显慢于同一作业的其它任务的情况。如果对这种情况不加优化,最慢的任务最终会拖慢整个作业的整体执行进度。好在mapreduce框架提供了任务推断执行机制,当有必要时就启动一个备份任务。最终会采用备份任务和原任务中率先执行完的结果作为最终结果。

由于具体分析推断执行机制,篇幅很长,所以我会分成几篇内容陆续介绍。

推断执行测试

本文在我自己搭建的集群(集群搭建可以参阅《Linux下Hadoop2.6.0集群环境的搭建》一文)上,执行wordcount例子,来验证mapreduce框架的推断机制。我们输入以下命令:

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0.jar wordcount -D mapreduce.input.fileinputformat.split.maxsize=19 /wordcount/input/ /wordcount/output/result1

任务划分的信息如下:


我们看到map任务被划分为10:


这一次测试并没有发生推断执行的情况,我们可以再执行一次上面的命令,最后看到的信息如下:


其中看到执行的map数量多了1个,成了11个,而且还出现了Killed map tasks=1的信息,这表示这次执行最终发生了推断执行。其中一个map任务增加了一个备份任务,当备份的map任务和原有的map任务中有一个率先完成了,那么会将另一个慢的map任务杀死。reduce任务也是类似,只不过Hadoop2.6.0的子项目hadoop-mapreduce-examples中自带的wordcount例子中,使用Job.setNumReduceTasks(int)这个API将reduce任务的数量控制为1个。在这里我们看到推断执行有时候会发生,而有时候却不会,这是为什么呢?

在《Hadoop2.6.0运行mapreduce之Uber模式验证》一文中我还简短提到,如果启用了Uber运行模式,推断执行会被取消。关于这些内部的实现原理需要我们从架构设计和源码角度进行剖析,因为我们还需要知道所以然。

mapreduce推断执行设计架构

在mapreduce中设计了Speculator接口作为推断执行的统一规范,DefaultSpeculator作为一种服务在实现了Speculator的同时继承了AbstractService,DefaultSpeculator是mapreduce的默认实现。DefaultSpeculator负责处理SpeculatorEvent事件,目前主要包括四种事件,分别是:

  • JOB_CREATE:作业刚刚被创建时触发的事件,并处理一些初始化工作。
  • ATTEMPT_START:一个任务实例TaskAttemptImpl启动时触发的事件,DefaultSpeculator将会使用内部的推断估算器(默认是LegacyTaskRuntimeEstimator)开启对此任务实例的监控。
  • ATTEMPT_STATUS_UPDATE:当任务实例的状态更新时触发的事件,DefaultSpeculator将会更新推断估算器对任务的监控信息;更新正在运行中的任务(维护在runningTasks中);任务的统计信息(这些统计信息用于跟踪长时间未汇报心跳的任务,并积极主动的进行推断执行,而不是等待任务超时)
  • TASK_CONTAINER_NEED_UPDATE:任务Container数量发生变化时触发的事件。

TaskRuntimeEstimator接口为推断执行提供了计算模型的规范,默认的实现类是LegacyTaskRuntimeEstimator,此外还有ExponentiallySmoothedTaskRuntimeEstimator。这里暂时不对其内容进行深入介绍,在后面会陆续展开。

Speculator的初始化和启动伴随着MRAppMaster的初始化与启动。

接下来我们以Speculator接口的默认实现DefaultSpeculator为例,逐步分析其初始化、启动、推断执行等内容的工作原理。

Speculator的初始化

SpeculatorMRAppMaster的子组件、子服务,所以也需要初始化。有经验的Hadoop工程师,想必知道当mapreduce作业提交给ResourceManager后,由RM负责向NodeManger通信启动一个Container用于执行MRAppMaster。启动MRAppMaster实际也是通过调用其main方法,其中会调用MRAppMaster实例的serviceInit方法,其中与Speculator有关的代码实现见代码清单1。

代码清单1 MRAppMaster的serviceInit方法中创建Speculator的代码

      if (conf.getBoolean(MRJobConfig.MAP_SPECULATIVE, false)
          || conf.getBoolean(MRJobConfig.REDUCE_SPECULATIVE, false)) {
        //optional service to speculate on task attempts' progress
        speculator = createSpeculator(conf, context);
        addIfService(speculator);
      }

      speculatorEventDispatcher = new SpeculatorEventDispatcher(conf);
      dispatcher.register(Speculator.EventType.class,
          speculatorEventDispatcher);

代码清单1所示代码的执行步骤如下:

  1. 当启用map任务推断(这里的MRJobConfig.MAP_SPECULATIVE实际由参数mapreduce.map.speculative控制,默认是true)或者启用reduce任务推断(这里的MRJobConfig.REDUCE_SPECULATIVE实际由参数mapreduce.reduce.speculative控制,默认是true)时调用createSpeculator方法创建推断服务。最后将Speculator添加为MRAppMaster的子服务。
  2. 向调度器dispatcher注册推断事件与推断事件的处理器SpeculatorEventDispatcher,以便触发了推断事件后交由SpeculatorEventDispatcher作进一步处理。

createSpeculator方法(见代码清单2)创建的推断服务的实现类默认是DefaultSpeculator,用户也可以通过参数yarn.app.mapreduce.am.job.speculator.class(即MRJobConfig.MR_AM_JOB_SPECULATOR)指定推断服务的实现类。

代码清单2 创建推断器

  protected Speculator createSpeculator(Configuration conf,
      final AppContext context) {
    return callWithJobClassLoader(conf, new Actio
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值