[Spark源码剖析] DAGScheduler划分stage

本文详细剖析Spark 1.3.1版本的DAGScheduler如何将Job划分为ShuffleMapStage和ResultStage。DAGScheduler根据ShuffleDependency划分Stage,每个Stage包含相同任务,Stage ID反映了其在DAG中的位置。文中逐步解析Stage创建过程,解释了Stage之间的依赖关系和ID的生成逻辑。

转载请标明出处:http://blog.csdn.net/bigbigdata/article/details/47293263

本文基于Spark 1.3.1

先上一些stage相关的知识点:

  1. DAGScheduler将Job分解成具有前后依赖关系的多个stage
  2. DAGScheduler是根据ShuffleDependency划分stage的
  3. stage分为ShuffleMapStage和ResultStage;一个Job中包含一个ResultStage及多个ShuffleMapStage
  4. 一个stage包含多个tasks,task的个数即该stage的finalRDD的partition数
  5. 一个stage中的task完全相同,ShuffleMapStage包含的都是ShuffleMapTask;ResultStage包含的都是ResultTask

下图为整个划分stage的函数调用关系图
这里写图片描述

在DAGScheduler内部通过post一个JobSubmitted事件来触发Job的提交

DAGScheduler.eventProcessLoop.post( JobSubmitted(...) )
DAGScheduler.handleJobSubmitted

既然这两个方法都是DAGScheduler内部的实现,为什么不直接调用函数而要这样“多此一举”呢?我猜想这是为了保证整个系统事件模型的完整性。

DAGScheduler.handleJobSubmitted部分源码及如下

private[scheduler] def handleJobSubmitted(jobId: Int,
      finalRDD: RDD[_],
      func: (TaskContext, Iterator[_]) => _,
      partitions: Array[Int],
      allowLocal: Boolean,
      callSite: CallSite,
      listener: JobListener,
      properties: Properties) {
    var finalStage: ResultStage = null
    try {
      //< 创建finalStage可能会抛出一个异常, 比如, jobs是基于一个HadoopRDD的但这个HadoopRDD已被删除
      finalStage = newResultStage(finalRDD, partitions.size, jobId, callSite)
    } catch {
      case e: Exception => 
        return
    }

    //< 此处省略n行代码
  }

该函数通过调用newResultStage函数来创建唯一的ResultStage,也就是finalStage。调用newResultStage时,传入了finalRDD、partitions.size等参数。

跟进到DAGScheduler.newResultStage

  private def newResultStage(
      rdd: RDD[_],
      numTasks: Int,
      jobId: Int,
      callSite: CallSite): ResultStage = {
    val (parentStages: List[Stage], id: Int) = getParentSt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值