Spark-Shuffle

Spark-Shuffle理解

     對spark任務劃分階段,遇到寬依賴會斷開,所以在stage 與 stage 之間會產生shuffle,大多數Spark作業的性能主要就是消耗在了shuffle環節,因爲該環節包含了大量的磁盤IO、序列化、網絡數據傳輸等操作。

    負責shuffle過程的執行、計算和處理的組件主要就是ShuffleManager,也即shuffle管理器。而隨着Spark的版本的發展,ShuffleManager也在不斷迭代。

   ShuffleManager 大概有兩個: HashShuffleManager 和 SortShuffleManager。

 歷史:

                在spark 1.2以前,默認的shuffle計算引擎是HashShuffleManager;

                在spark 1.2以後的版本中,默認的ShuffleManager改成了SortShuffleManager;

                在spark 2.0以後,拋棄了 HashShuffleManager。

HashShuffleManager

假設:每個Executor只有1個CPU core,也就是說,無論這個Executor上分配多少個task線程,同一時間都只能執行一個task線程。

 上游 stage 有 2個 Executor,每個Executor 有 2 個 task。

           下游 stage 有 3個task。

shuffle write階段:

          將相當於mapreduce的shuffle write,按照key的hash 分桶,寫出中間文件。上游的每個task寫自己的文件。

          寫出中間文件個數 = maptask的個數 *  reducetask的個數

 上圖寫出的中間文件個數 = 4 * 3 = 12 

 假設上游 stage 有 10 個Executor,每個 Executor有 5 個task,下游stage 有 4 個task,寫出的中間文件數 = (10 * 5) * 4 = 200 個,由此可見,shuffle write操作所產生的磁盤文件的數量是極其驚人的。

shuffle read 階段:

           就相當於mapreduce 的 shuffle read, 每個reducetask 拉取自己的數據。

           由於shuffle write的過程中,task給下游stage的每個task都創建了一個磁盤文件,因此shuffle read的過程中,每個task只要從上游stage的所有task所在節點上,拉取屬於自己的那一個磁盤文件即可。

 弊端:

        shuffle write階段佔用大量的內存空間,會導致頻繁的GC,容易導致OOM;也會產生大量的小文件,寫入過程中會產生大量的磁盤IO,性能受到影響。適合小數據集的處理。          

SortShuffleManager

   Spark在引入Sort-Based Shuffle以前,比較適用於中小規模的大數據處理。爲了讓Spark在更大規模的集羣上更高性能處理更大規模的數據,於是就引入了SortShuffleManager。

 shuffle write 階段:

  

SortShuffleManager不會爲每個Reducer中的Task生成一個單獨的文件,相反,會把上游中每個mapTask所有的輸出數據Data只寫到一個文件中。並使用了Index文件存儲具體 mapTask 輸出數據在該文件的位置。

        因此 上游 中的每一個mapTask中產生兩個文件:Data文件 和 Index 文件,其中Data文件是存儲當前Task的Shuffle輸出的,而Index文件中存儲了data文件中的數據通過partitioner的分類索引。

        寫出文件數 = maptask的個數 * 2  (index 和  data )

        可見,SortShuffle 的產生的中間文件的多少與 上個stage 的 maptask 數量有關。

shuffle read 階段:

    下游的Stage中的Task就是根據這個Index文件獲取自己所要抓取的上游Stage中的mapShuffleMapTask產生的數據的;

總結:

Hash Shuffle:M*R;

 Sort Shuffle:2*M;

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