圖解spark的任務構建和提交流程

簡述spark的任務運行流程

先是在寫spark代碼的時候,背後做一些RDD的轉換,寫完後構建DAG,劃分stage, 然後提交到資源管理器分配計算資源, 並在worker上執行。
在這裏插入圖片描述

首先寫spark代碼時離不開對RDD的調用,那麼:

爲什麼需要RDD

  1. 數據處理模型統一:
    RDD是1個數據結構, 能夠獲取數據的分區。
    不區分流式還是批式,只理解爲1個數學模型。

  2. 依賴劃分原則:
    RDD之間通過窄依賴(僅1個依賴)和寬依賴(多依賴)進行關聯。
    爲什麼要劃分依賴?
    依賴數量不同,決定是否能在1個stage和節點中執行。
    同時也決定了容災策略,是否需要保存所有父RDD

  3. 數據處理效率:
    1個RDD,同時可在多個節點併發執行。

  4. 容錯處理:
    RDD本身是不可變的數據集,這樣可保證數據恢復在這裏插入圖片描述

wordCount代碼的背後

以wordCount代碼爲例

textFile

第一步是讀文件數據。

JavaSparkContext ctx = new JavaSparkContext(sparkConf);
ctx.textFile(args[0],1)

這一步會生成HadoopRDD
在這裏插入圖片描述
這裏注意下, 裏面有一個清理序列化的操作, 分佈式傳輸數據時,序列化很重要,而序列化時有些成員是無法被序列化的,在java中的關鍵字是transien.

MappedRDD是什麼?
如下:
在這裏插入圖片描述
即我們的RDD,會被包裝到一個單點依賴的對象裏,並指明這是單點依賴。
並且textFile這個過程, 其實是生成了2個RDD, 1個是HadoopRDD,還有一個是讀取數據轉成字符串的mapRDD。 他們各自被塞進dependecy對象中,並通過依賴建立連接。

  • 注意,一般分佈式計算設計DAG圖時, 都是隻有input指針(即用輸入對象做連接), 利用input來確定DAG關係。 在spark裏就是依賴dependency的概念

第二步做FlatMap

接着我們調用flatMap

JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>(){
	@Override
	public Iterable<String> call(String s){
	return Arrays.asList(SPACE.split(s));
}) 

背後的RDD和依賴i情況變成如下:
在這裏插入圖片描述

第三步mapToPair

懶得敲了,這裏省略java代碼。
在這裏插入圖片描述
看一下dag。
在這裏插入圖片描述

第四步聚合

需要分組,然後進行合併相同的單詞數量
在這裏插入圖片描述
此時dag如下:
在這裏插入圖片描述

  • 注意, 並不是shuffle這個RDD被包裝進了shuffle依賴, 而是它的前置RDD被包進了shuffle依賴。
  • 即dependency確實是只包裝依賴的, 你如果是屬於某個shuffle過程的依賴,那麼就會被包裝成shuffleDepnecy。

最後一步collect

當寫完後,執行collet,進行計算執行和提交。
在這裏插入圖片描述

完整流程如下:
在這裏插入圖片描述

Collect的時候發生了什麼

collect後, 會通過dagScheduler進行runJob, submitJob的時候會返回一個waiter,在client端主程序中就會進行等待。
即client端提交任務時其實是異步的,會返回一個waiter進行等待,
在這裏插入圖片描述

看一下submitJob的時候發生了什麼
在這裏插入圖片描述
前面看起來都是一些業務處理, 關鍵在handleJobSumitted的時候,會做一個newStage的操作,正好可以看一下spark裏的stage是怎麼確定和生成的。
在這裏插入圖片描述
父(依賴)stage列表是怎麼獲取的?
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200701234813809.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3OTk1ODE
上圖裏的關鍵信息在於, 當遇到shuffle的時候,就會隔離出一個stage。

可以看一下之前提到的RDD拼成的DAG圖,如下:
在這裏插入圖片描述

newStage後,有如下情況:
在這裏插入圖片描述
可以看到又給stage裏有一個rdds的數組, 裏面放了該stage的所有RDD, 並建立了依賴關係。
然後每個stage又通過parent去確定依賴關係。

stage提交

newStage之後,會進行stage的提交
在這裏插入圖片描述

看一下submitStage的時候做了什麼,注意此時是先從finalStage開始提交的。
在這裏插入圖片描述
這裏可以看到, 雖然我們做了finalStage的提交, 但是會優先提交它所依賴的前置stage, 一直等待stage 完成了再真正提交自己這個stage。

這裏看一下 stage是怎麼發送的
在這裏插入圖片描述
上圖可以看到stae座位task時,也是區分shuffle類型和map類型。
在這裏插入圖片描述

  • 這句話重點: 有多少個未計算的分區,決定了有多少個task, 即stage中的分區和task一一對應

完成的stage創建和提交流程圖如下:
在這裏插入圖片描述

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