Spark driver啟動Task的流程

Spark內部有兩大類操作,Transformation和Action;
Transformation又分窄依賴操作和寬依賴操作,區分這兩種操作的很簡單,RDD之間轉化過程中沒有shuffle的就是窄依賴,有shuffle的就是寬依賴:

  1. RDD中數據是分partition的,每個partition分布在特定節點,shuffle就是指在RDD在轉化過程中,一個partition中的數據需要被split成多個分片,傳入到下游RDD中的多個partition中去,比如reduceByKey這類的操作,實際生產中,下游partition中的數據往往依賴于上游多個partition的數據,這樣就是會產生一個問題,如果下游某個partition中的數據缺失,需要重新計算上游多個partition的數據,而重新計算的這些上游partition中又會同時含有下游缺失的數據partition和正常的partition,這就會造成計算的冗余;
  2. 與之相對的是窄依賴計算,上游一個或多個partition只對應下游一個partition,所以下游某個節點故障后,某個partition缺失數據,上游需要計算的所有partition不含有冗余計算,比如map,filter,union等等;

Spark數據集是RDD,如果數據類型是Tuple2,還提供PariRDDFunctions的一些方法(是通過object RDD addToPariFuncitons隱式包含進來的):

  1. 如果是窄依賴,比如map操作,生成
    new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF));
  2. 如果是寬依賴,比如reduceByKey操作,生成
new ShuffledRDD[K, V, C](self, partitioner) 
.setSerializer(serializer) 
.setAggregator(aggregator) 
.setMapSideCombine(mapSideCombine);

其中aggregator定義了數據merge的規則,這個merge包括在map端(類似hadoop中的combiner,也就是partition內部數據merge的規則)和reduce端(partition之間數據merge的規則),這個merge可以是多個value組成更大的集合,例如groupByKey,也可以是多個value合并計算出新的value,比如word count作業中的reduceByKey,根據業務邏輯而定; mapSideCombine是一個boolean,表示是否需要在map端進行merge操作,比如reduceByKey是true,groupByKey是false;
首先來看一下MapPartitionRDD:

private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](    
  var prev: RDD[T],
  f: (TaskContext, Int, Iterator[T]) => Iterator[U], // (TaskContext, partition index, iterator)
  preservesPartitioning: Boolean = false)  
 extends RDD[U](prev) {
  override val partitioner = if (preservesPartitioning) firstParent[T].partitioner else None         
  override def getPartitions: Array[Partition] = firstParent[T].partitions    
  override def compute(split: Partition, context: TaskContext): Iterator[U] =        
    f(context, split.index, firstParent[T].iterator(split, context)) 
  override def clearDependencies() {
    super.clearDependencies()    
    prev = null  
  }
}

其中partitioner(默認HashPartitioner)定義如果存在shuffle,不同的key被shuffle到下游的那一個分片(partition)中去,對于MapPartitionsRDD,不存在這樣的情況;每個RDD都會維護自己的dependencies,是一個Seq,這里的dependency可能是OneToOneDependency(一對一,例如map),可能是RangeDependency(例如union,兩個RDD合并成一個,但是partition不會發生merge,上游RDD多個partition會變成下游RDD的partition range),也可能是ShuffleDependency;
firstParent這里就是dependencies中的第一個,map操作,上游只有一個RDD,也就是只有一個partition,compute操作很簡單,通過split指定上游partition,對其執行f函數,返回的也是一個Iterator,其中firstParent[T].iterator,如果沒有cache或checkpoint則也是一個compute實現;
上面的結果就是RDD內部層層套RDD,最后計算(compute)的時候,由里到外,不斷的遍歷iterator,完成計算,這里直觀感覺上是遍歷多次,但基于scala內部的實現,減少不必要的遍歷;
下面再看ShuffledRDD:
compute內部通過shuffleManager獲取上游shuffle-write產生的數據,根據split,返回iterator,并不包涵其他的函數計算:

  override def compute(split: Partition, context: TaskContext): Iterator[(K, C)] = { 
    val dep = dependencies.head.asInstanceOf[ShuffleDependency[K, V, C]]       
    SparkEnv.get.shuffleManager.getReader(dep.shuffleHandle, split.index, split.index + 1, context).read().asInstanceOf[Iterator[(K, C)]]  
  }

下面來看一下調用rdd.collect(Spark的Action操作)之后stage的劃分,最后直接的處理函數是handleJobSubmitted,
finalStage = newResultStage(finalRDD, func, partitions, jobId, callSite);
Stage這里面涉及到兩種ResultStage和ShuffleMapStage,每一個Stage都包含若干parent stages,對于這種一對一的RDD DAG 作業,parent stages這個集合中,保存的都只是上游1個stage,是一個單鏈條;劃分Stage的方法很簡單,就是通過ShuffleDependency來判斷;
stage都確定好之后,將stage轉化為task進行計算,計算的條件就是一個stage的所有parent stges都已經計算完成,stage到task的邏輯是:submitMissingTasks;
val partitionsToCompute: Seq[Int] = stage.findMissingPartitions()
首先得到需要計算哪些partition,然后根據ShuffleMapStage和ResultStage分別生成ShuffleMapTask和ResultTask,然后提交task:
taskScheduler.submitTasks(new TaskSet(tasks.toArray, [stage.id](http://stage.id), stage.latestInfo.attemptId, jobId, properties))
CoarseGrainedExecutorBackend收到LaunchTask之后:

case LaunchTask(data) =>  if (executor == null) {
  logError("Received LaunchTask command but executor was null")
  System.exit(1)  
} else {    
  val taskDesc = ser.deserialize[TaskDescription](data.value)    
  logInfo("Got assigned task " + taskDesc.taskId)    
  executor.launchTask(this, taskId = taskDesc.taskId, attemptNumber = taskDesc.attemptNumber, taskDesc.name, taskDesc.serializedTask)
}

通過executor執行task。
補充說明一點,整個RDD的DAG圖根據ShuffleDependency劃分出若干stage之后,或者是一個ShuffleMapStage,或者是一個ResultStage,對于ResultStage很簡單,從上游讀取數據,聚合之后就可以返回了,對于ShuffleMapStage,他的目標就是完成Shuffle-Write操作,這個實在ShuffleMapTask中的runTask完成的,而需要讀取的數據由上游的RDD的iterator提供,上游如果是普通的RDD,比如MapPartitionsRDD,直接讀取,內部的compute函數完成兩個事情,第一提供iterator,第二完成上游RDD的計算邏輯,即用函數對iterator操作,而這個提供數據iterator又回繼續遞歸調用更上游的RDD的compute,但是如果是ShuffledRDD,則不會遞歸到更上游,而是去reader,讀取上游數據,返回iterator,僅此而已,reader的實現中是到driver拿到mapstatuses,里面包括block的executor位置信息,然后連接executor進行讀取。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容