spark(五)執行流程與stage劃分

一、任務流程

我們以生產中常用的yarn環境爲例

  • 提交任務到yarn
  • yarn申請分配資源
  • 根據RDD流程構建DAG(有向無環圖)
  • DAGsheduler將dag劃分及分解stage
  • 根據分解的stage生成不同的task
  • 將task提交到不同的Executor上執行
  • 執行完畢,釋放資源

二、線程模型

Spark任務的線程模型特點:

  • 每個節點上可以運行一個或多個Executor服務。每個應用程序在一個工作者節點上只會有一個Executor。多個應用程序則會有多個Executor
  • 每個Executor配有一定數量的slot,表示該Executor中可以同時運行多少個ShuffleMapTask或者ReduceTask;
  • 每個Executor單獨運行在一個JVM進程中,每個Task則是運行在Executor中的一個線程;
  • 同一個Executor內部的Task可共享內存,比如通過函數SparkContext.broadcast廣播的數據如文件或者數據結構只會在每個Executor中加載一次,而不會像MapReduce那樣,每個Task加載一次
  • Executor一旦啓動後,將一直運行,且它的資源可以一直被Task複用,直到Spark程序運行完成後才釋放退出。
  • 總體上看,Spark採用的是經典的scheduler/workers模式,每個Spark應用程序運行的第一步是構建一個可重用的資源池,然後 在這個資源池裏運行所有的ShuffleMapTask和ReduceTask(注意,儘管Spark編程方式十分靈活,不再侷限於編寫Mapper和 Reducer,但是在Spark引擎內部只用兩類Task便可表示出一個複雜的應用程序,即ShuffleMapTask和ResultTask),而 MapReduce應用程序則不同,它不會構建一個可重用的資源池,而是讓每個Task動態申請資源,且運行完後馬上釋放資源

三、shuffle

大多數spark作業的性能主要就是消耗了shuffle過程,shuffle時數據會重新分片並寫磁盤,該環節包含了大量的磁盤IO、序列化、網絡數據傳輸等操作。因此,如果要讓作業的性能更上一層樓,就有必要對shuffle過程進行調優。但是也必須提醒大家的是,影響一個Spark作業性能的因素,主要還是代碼開發、資源參數以及數據傾斜,shuffle調優只能在整個Spark的性能調優中佔到一小部分。

四、寬依賴與窄依賴

如下圖,一個父rdd數據有可能進入多個rdd的操作都會產生寬依賴,相反一個父rdd數據只進入一個子rdd稱爲窄依賴。
注意,union 操作如果先分組後union,且沒有改變分區器,此時union不會產生寬依賴。
在這裏插入圖片描述

五、stage的劃分

產生寬依賴時,數據會產生shuffle,shuffle後的操作依賴於shuffle前的操作結果全部完畢才能開始。
在DAG調度的過程中,Stage階段的劃分是根據是否有shuffle過程,也就是存在ShuffleDependency寬依賴的時候,需要進行shuffle,這時候會將作業job劃分成多個Stage;
spark 劃分 stage 的整體思路是:從後往前推,遇到寬依賴就斷開,劃分爲一個 stage;遇到窄依賴就將這個 RDD 加入該 stage 中。如下圖:
在這裏插入圖片描述

六、stage生成Task 的類型

在 spark 中,Task 的類型分爲 2 種:ShuffleMapTask 和 ResultTask
DAG 的最後一個階段會爲每個結果的 partition 生成一個 ResultTask,即每個 Stage裏面的 Task 的數量是由該 Stage 中最後一個 RDD 的 Partition 的數量所決定的。而其餘所有階段都會生成 ShuffleMapTask;之所以稱之爲 ShuffleMapTask 是因爲它需要將自己的計算結果通過 shuffle 到下一個 stage 中;

七、spark shuffle四種策略:

負責shuffle過程的執行、計算和處理的組件主要就是ShuffleManager,也即shuffle管理器。
ShuffleManager隨着Spark的發展有兩種實現的方式,分別爲HashShuffleManager(spark1.2之前使用)和SortShuffleManager,因此spark的Shuffle有Hash Shuffle和Sort Shuffle兩種

在Spark 1.2以前,默認的shuffle計算引擎是HashShuffleManager。該ShuffleManager而HashShuffleManager有着一個非常嚴重的弊端,就是會產生大量的中間磁盤文件,進而由大量的磁盤IO操作影響了性能。因此在Spark 1.2以後的版本中,默認的ShuffleManager改成了SortShuffleManager。SortShuffleManager相較於HashShuffleManager來說,有了一定的改進。主要就在於,每個Task在進行shuffle操作時,雖然也會產生較多的臨時磁盤文件,但是最後會將所有的臨時文件合併(merge)成一個磁盤文件,因此每個Task就只有一個磁盤文件。在下一個stage的shuffle read task拉取自己的數據時,只要根據索引讀取每個磁盤文件中的部分數據即可。
總體來說就是:

spark1.2版本以前:hashShuffleManager
	未經優化的hashShuffleManager(會產生大量小文件)
	經過優化的hashShuffleManager(後續task可以複用之前的文件)
spark1.2版本以後:SortShuffleManager
	普通機制(將小文件合併爲大一個文件,寫磁盤前會對數據進行key排序)
	ByPass機制(將小文件合併爲大一個文件,不會排序)

八、spark 的shuffle調優:

主要是調整緩衝的大小,拉取次數重試重試次數與等待時間,內存比例分配,是否進行排序操作等等

  • spark.shuffle.file.buffer
    參數說明:該參數用於設置shuffle write task的BufferedOutputStream的buffer緩衝大小(默認是32K)。將數據寫到磁盤文件之前,會先寫入buffer緩衝中,待緩衝寫滿之後,纔會溢寫到磁盤。
    調優建議:如果作業可用的內存資源較爲充足的話,可以適當增加這個參數的大小(比如64k),從而減少shuffle write過程中溢寫磁盤文件的次數,也就可以減少磁盤IO次數,進而提升性能。在實踐中發現,合理調節該參數,性能會有1%~5%的提升。

  • spark.reducer.maxSizeInFlight:
    參數說明:該參數用於設置shuffle read task的buffer緩衝大小,而這個buffer緩衝決定了每次能夠拉取多少數據。
    調優建議:如果作業可用的內存資源較爲充足的話,可以適當增加這個參數的大小(比如96m),從而減少拉取數據的次數,也就可以減少網絡傳輸的次數,進而提升性能。在實踐中發現,合理調節該參數,性能會有1%~5%的提升。

  • spark.shuffle.io.maxRetries and spark.shuffle.io.retryWait:
    spark.shuffle.io.retryWait:huffle read task從shuffle write task所在節點拉取屬於自己的數據時,如果因爲網絡異常導致拉取失敗,是會自動進行重試的。該參數就代表了可以重試的最大次數。(默認是3次)
    spark.shuffle.io.retryWait:該參數代表了每次重試拉取數據的等待間隔。(默認爲5s)
    調優建議:一般的調優都是將重試次數調高,不調整時間間隔。

  • spark.shuffle.memoryFraction:
    參數說明:該參數代表了Executor內存中,分配給shuffle read task進行聚合操作的內存比例。

  • spark.shuffle.manager
    參數說明:該參數用於設置shufflemanager的類型(默認爲sort)。Spark1.5x以後有三個可選項:

Hash:spark1.x版本的默認值,HashShuffleManager
Sort:spark2.x版本的默認值,普通機制,當shuffle read task 的數量小於等於spark.shuffle.sort.bypassMergeThreshold參數,自動開啓bypass 機制
tungsten-sort:
  • spark.shuffle.sort.bypassMergeThreshold
    參數說明:當ShuffleManager爲SortShuffleManager時,如果shuffle read task的數量小於這個閾值(默認是200),則shuffle write過程中不會進行排序操作。
    調優建議:當你使用SortShuffleManager時,如果的確不需要排序操作,那麼建議將這個參數調大一些

  • spark.shuffle.consolidateFiles:
    參數說明:如果使用HashShuffleManager,該參數有效。如果設置爲true,那麼就會開啓consolidate機制,也就是開啓優化後的HashShuffleManager。
    調優建議:如果的確不需要SortShuffleManager的排序機制,那麼除了使用bypass機制,還可以嘗試將spark.shffle.manager參數手動指定爲hash,使用HashShuffleManager,同時開啓consolidate機制。在實踐中嘗試過,發現其性能比開啓了bypass機制的SortShuffleManager要高出10%~30%。

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