|NO.Z.00091|——————————|BigDataEnd|——|Hadoop&Spark.V07|——|Spark.v07|Spark 原理 源码|作业执行原理&Stage划分&提交ResultStage|

一、Stage划分
### --- 提交ResultStage

~~~     submitStage 方法会通过入参 ResultStage 逐层获取父stage,
~~~     再从最上游stage开始逐步调用TaskScheduler.submitTasks 方法提交task集合,
~~~     最后才提交ResultStage的task集合。
~~~     先调用getMissingParentStages来获取是否有未提交的父stages。
~~~     若有,则依次递归提交父stages,并将missing加入到waitingStages中。
~~~     对于要依次提交的父stage,也是如此;
~~~     若missing存在未提交的父stages,则先提交父stages;
~~~     这时会调用submitMissingTasks(stage, jobId.get),参数就是missing及其对应的jobId.get。
~~~     这个函数便是将stage与taskSet对应起来,
~~~     然后DAGScheduler将taskSet提交给TaskScheduler去执行的实施者。
二、源码提取说明
### --- 源码提取说明

~~~     # 源码提取说明:DAGScheduler.scala
~~~     # 1061~1082private def submitStage(stage: Stage) {
    // 获取当前Stage对应的Job的ID
    val jobId = activeJobForStage(stage)
    if (jobId.isDefined) { // Job ID是定义的
      logDebug("submitStage(" + stage + ")")
      if (!waitingStages(stage) && !runningStages(stage) && !failedStages(stage)) { //当前Stage未提交
        // 获取当前Stage的所有未提交的父Stage
        val missing = getMissingParentStages(stage).sortBy(_.id)
        logDebug("missing: " + missing)
        if (missing.isEmpty) { // 不存在未提交的父Stage
           logInfo("Submitting " + stage + " (" + stage.rdd + "), which has no missing parents") 
          // 提交当前Stage所有未提交的Task
          submitMissingTasks(stage, jobId.get)
        } else { // 存在未提交的父Stage
          // 提交所有未提交的父Stage
          for (parent <- missing) {
            submitStage(parent)
            
            } 
          // 并且将当前Stage加入waitingStages集合中,当前Stage必须等待所有父Stage执行完成
          waitingStages += stage
        }
      }
    } else { // Job ID未定义,放弃提交当前Stage
      abortStage(stage, "No active job for stage " + stage.id, None)
    }
  }
~~~     # 源码提取说明:DAGScheduler.scala
~~~     # 550行~574// 获取Stage的所有未提交的父Stage
  // private def getMissingParentStages(stage: Stage): List[Stage] = {
  val missing = new HashSet[Stage]
  val visited = new HashSet[RDD[_]]
  // We are manually maintaining a stack here to prevent StackOverflowError
  // caused by recursively visiting
  val waitingForVisit = new Stack[RDD[_]]
  // 定义visit()方法
  def visit(rdd: RDD[_]) {
    // 判断是否已经处理过
    if (!visited(rdd)) { // 未处理过
      // 添加到已处理集合进行记录
      visited += rdd
      /**
       * 获取RDD各个分区的TaskLocation序列,判断是否包含Nil。
       * Stage的RDD的分区中存在没有对应TaskLocation序列的分区,
       * 则说明当前Stage的某个上游ShuffleMapStage的某个分区任务未执行。
       */
      val rddHasUncachedPartitions = getCacheLocs(rdd).contains(Nil)
      if (rddHasUncachedPartitions) { // TaskLocation序列包含Nil
        // 遍历该rdd的所有依赖
        for (dep <- rdd.dependencies) {
          dep match {
            case shufDep: ShuffleDependency[_, _, _] => // 是ShuffleDependency
              // 获取该ShuffleDependency的上游第一个提交的ShuffleMapStage
              val mapStage = getOrCreateShuffleMapStage(shufDep, stage.firstJobId)
              if (!mapStage.isAvailable) { // 该ShuffleMapStage不可用
                // 将其添加到missing集合进行记录
                missing += mapStage
              } 
            case narrowDep: NarrowDependency[_] => // 是NarrowDependency
              // 将该窄依赖的rdd压入waitingForVisit栈中
            waitingForVisit.push(narrowDep.rdd)
          }
        }
      }
    }
  }

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

 

posted on   yanqi_vip  阅读(18)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示