Spark — Shuffle操作

Spark的shuffle操作

  Spark的shuffle操作分爲HashShuffle和SortShuffle,兩種shuffle(還有一種tungsten-sort shuffle,這個沒有研究過)。其中在Spark1.2版本之前默認的都是HashShuffle操作,HashShuffle有一個非常嚴重的弊端就是在沒有開啓consolidation機制的情況下,會產生大量的中間磁盤文件,這對性能有很大的影響;而在Spark1.2版本之後,默認的Shuffle,就改成了SortShuffle,相比於HashShuffle,SortShuffle雖然也會產生中間文件,但是在map output的時候,會將這些臨時文件進行聚合,生成一個磁盤文件,因此每個Task就只有一個磁盤文件,reduce在拉取數據的時候,根據索引中的位移信息就可以拉取到自己的信息。
  在知道Spark Shuffle有不同的版本之後,我們先從老版本開始分析,之前設計的shuffle的弊端在哪裏,然後在分析新的版本。(這裏分析的前提條件是,數據比較大,內存緩存不夠,會溢寫到磁盤,假如數據量很小,那麼差距也就不大了)

HashShuffle
未開啓consolidation機制

  發生shuffle的操作,主要是使用到了對key進行操作的算子,比如reduceByKey、groupByKey等。
  普通的shuffle操作,如下圖所示:
普通shuffle
  假設每個worker的每個executor只有一個cpu core,意思就是每個時間只有一個task在運行,reduce端有4個task。在普通機制下,map端的每個task都會爲reduce端的task創建一份屬於它的文件,也就是說每個ShuffleMapTask會爲每個ReduceTask創建一份屬於它的文件,那麼就創建了4個文件,假設map端有4個Task並行運行,那麼這個stage結束之後,就會創建16分臨時文件。

開啓了consolidation機制

  假設開啓了consolidation機制的HashShuffle,它的過程如下:
consolidation
  和上述一樣的情況,開啓了Consolidation機制的shuffle,在Map端輸出文件的時候,每一個節點上的Task,在第一個task運行的時候創建了4個對應ReduceTask的文件,在這個Task運行結束,下一個Task開始的時候,就會複用之前的Task創建的文件,不會在創建新的文件。因此整個stage運行結束後,只創建了8個文件,相比於之前的普通機制,少了8個。
  雖然HashShuffle在開啓了Consolidation機制後,磁盤文件減少很多,但是在task數量很多的時候,產生的磁盤文件依然很可觀,比如10個executor,每個executor 5個cpu core,reduce端task數量是50個,那麼會產生 10 * 5 * 50 = 2500個磁盤文件,依然很多。而SortShuffle卻沒有這種情況,它的每個Task只會爲所有的ReduceTask創建一份文件 ,加上一份索引文件,記錄每個partition的數據位置。下面我們先分析一下它的原理。

SortShuffle
普通機制

  SortShuffle的普通機制是在ReduceTask小於200(spark.shuffle.sort.bypassMergeThreshold默認是200)的時候,運行的就是普通機制,超過就是bypass機制。普通機制它會對數據先進行排序,然後再寫入到文件。而bypass機制沒有排序這個環節。下面先看圖:
在這裏插入圖片描述
  首先Task會將數據存入緩存,當達到一定閾值之後(32K),就會根據key將數據進行排序,排序後分批寫入磁盤文件,默認是10000條,也就是說數據會以每批10000條的數據分批寫入磁盤(寫入磁盤是使用的Java BufferedOutputStream,會先將數據緩存在內存中,當緩存溢滿之後再寫入磁盤,減少IO操作),產生一個臨時文件。在數據量比較大的時候,一個Task將數據寫入內存的時候,可能會產生多個臨時文件,在Task結束的時候,會將這些臨時文件進行聚合merge成一個文件,寫入磁盤,並且還生成一個索引文件,記錄每個partition的數據位置(Offset)。

bypass機制

bypass
  相比於普通機制,bypass它沒有排序這一個功能,它的每個Task都會爲ReduceTask創建一個文件,這和未開啓consolidation機制的HashShuffle是一樣的,不同的是,它在最後做了一個合併文件的操作,並創建一個單獨的索引。這對於ResultTask而言read的性能會更好些。
  目前Spark1.2版本之後默認使用的是,SortShuffle,它的兩種機制上面已經分析過了,最主要的區別就是一個會排序,一個不需要排序,它們相對於HashShuffle而言,Task端最終輸出的文件要少的多,其實在產生的臨時文件的數量上,SortShuffle同樣不少,它就和未開啓Consolidation機制的HashShuffle一樣,這點需要注意。不過既然Spark一直保留着HashShuffle,應該也有它的用處。

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