(八)Spark源碼理解之DAGScheduler---part2

承接上篇博文所述,接下來我對getShuffleMapStage以及newStage這兩個方法的代碼進行主要的介紹

getShuffleMapStage:該方法主要是通過調用newOrUsedStage生成stage

private def getShuffleMapStage(shuffleDep: ShuffleDependency[_,_], jobId: Int): Stage = {
    shuffleToMapStage.get(shuffleDep.shuffleId) match {
      case Some(stage) => stage//如果該stage已經存在,則返回這個stage
      case None =>//否則生成新的stage
        val stage =
          newOrUsedStage(shuffleDep.rdd, shuffleDep.rdd.partitions.size, shuffleDep, jobId)
        shuffleToMapStage(shuffleDep.shuffleId) = stage  //將生成的stage存儲在相應的容器中,以標誌其已經存在,避免後續的過程中又生成
        stage  //返回stage
    }
  }

newOrUsedStage:該方法主要是通過調用newStage方法爲特定的shuffle依賴生成stage,即生成Stage類,此外若MapOutTracker中已經存在該shuffle所對應的的stage,我們就恢復其輸出位置,輸出位置存儲的其實就是MapStatus,否則MapOutTracker就會註冊該stage,從之前MapOutTracker章節中已經得知MapOutTracker就是用於管理shuffle操作的

newStage:該方法真正的實現創建一個stage,同時在創建stage之後更新job和stage的關係,即更新前面最開頭(Spark源碼理解之DAGScheduler---part1)提到的幾個重要的變量

private def newStage(
      rdd: RDD[_],
      numTasks: Int,
      shuffleDep: Option[ShuffleDependency[_,_]],
      jobId: Int,
      callSite: Option[String] = None)
    : Stage =
  {
    val id = nextStageId.getAndIncrement()//生成stage的id
    val stage =
      new Stage(id, rdd, numTasks, shuffleDep, getParentStages(rdd, jobId), jobId, callSite)//生成Stage類
    stageIdToStage(id) = stage//更新消息
    updateJobIdStageIdMaps(jobId, stage) //更新job和stage對應的關係
    stageToInfos(stage) = StageInfo.fromStage(stage)
    stage
  }

updateJobIdStageIdMaps:該方法主要實現更新job和stage的映射關係,通過更新前面所說的相關容器實現

PS:生成shuffle mapstage的時候調用newOrUsedStage(),而生成final stage的時候直接調用newStage(),這在之後會提到,因爲生成shuffle map stage的時候還要通過MapOutTracker進行各種shuffle註冊,標記等等,newOrUsedStage()方法正好實現了這一部分,而newStage()方法沒有

關於shuffle的依賴我覺得始終很模糊,希望有機會可以解決?????

此外,始終不太明白任務集不是由分區所進行的各個操作即函數所組成嘛,那這些函數都存放在哪裏,調用Task.run的時候怎麼運行的,難道是由Task類的回調函數所實現,如果是這樣,那是在哪個部分進行的呢,回調函數是怎麼將這些函數添加進來的呢????希望能得到各位博友的熱心解答

Stage類中的變量只有一個RDD,那是不是說一個stage只有一個RDD,寫程序時一般在創建完SparkContext對象之後就會將我們的scala集合通過parallize()方法轉換爲RDD,之後進行各種操作,那從這裏可以看出我們最開始也就只有一個RDD,之後我們就是對這一個RDD進行操作,因此一個stage只有一個RDD這樣的理解應該也是沒錯的,即使我們會生成多個RDD,但我認爲在觸發動作時多個RDD應該也會轉換爲一個RDD

接下來,可以看看DAGScheduler如何向TaskScheduler提交任務集

其大概思路可以概述爲如下:

首先生成一個任務數組tasks,用來存放之後的任務集,tasks爲該stage的任務集---->若該stage爲shuffle map stage,則生成ShuffleMapTask,若爲final stage,則生成ReusltTask,之後將生成的ShuffleMapTask或者ReusltTask存放在tasks中----->tasks生成TaskSet類,接着調用TaskScheduler的submitTasks()方法提交剛剛生成的任務集

至此,DAGScheduler完成了將任務集提交給TaskScheduler

前面的文章中提及過Task的類型有ShuffleMapTask和ResultTask,下篇博文中我將就這兩種任務的區別進行簡單地講述。。。

未完待續。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章