簡要MR與Spark在Shuffle區別

狗子毛豆子貓發表於2021-01-18

一、區別

①本質上相同,都是把Map端資料分類處理後交由Reduce的過程。

②資料流有所區別,MR按map, spill, merge, shuffle, sort, r

educe等各階段逐一實現。Spark基於DAG資料流,可實現更復雜資料流操作(根據寬/窄依賴實現)

③實現功能上有所區別,MR在map中做了排序操作,而Spark假定大多數應用場景Shuffle資料的排序操作不是必須的,而是採用Aggregator機制(Hashmap每個元素<K,V>形式)實現。(下面有較詳細說明)

ps:為了減少記憶體使用,Aggregator是在磁碟進行,也就是說,儘管Spark是“基於記憶體的計算框架”,但是Shuffle過程需要把資料寫入磁碟

二、MR中的Shuffle

在MR框架中,Shuffle是連線Map和Reduce之間的橋樑,Map的輸出結果需要經過Shuffle過程之後,也就是經過資料分類以後再交給Reduce進行處理。因此,Shuffle的效能高低直接影響了整個程式的效能和吞吐量。由此可知,Shuffle是指對Map輸出結果進行分割槽、排序、合併等處理並交給Reduce的過程。因此,MapReduce的Shuffle過程分為Map端的操作和Reduce端的操作,如下圖:

簡單點說: Map端Shuffle過程,就是對Map輸出結果寫入快取、分割槽、排序、合併再寫入磁碟。
Reduce端Shuffle過程,就是從不同Map機器取回輸出進行歸併後交給Reduce進行處理。

三、Spark中的Shuffle

①、Spark作為MR框架的改進,也實現了Shuffle的邏輯,如下圖:

Map端的Shuffle寫入(Shuffle Write)方面,每個Map根據Reduce任務的數量創造相應桶數量m*r(桶為抽象概念,m是map任務r是reduce任務),Map任務產生的結果根據分割槽演算法(預設hash)到不同桶中。當Reduce任務啟動時,會根據自己任務的id和所依賴的Map任務的id,從遠端或本地取得對應的桶,作為Reduce任務的輸入進行處理。

ps:在Spark1.2的版本後,Shuffle引擎改為SortShuffleManager(原來為HashShuffleManager),也就是把每個Map任務所有輸出資料都寫到同一個任務中,避免小檔案太多對效能的影響。因此Shuffle過程中,每個Map任務會產生資料檔案及所有檔案兩個。

②、在Reduce端的Shuffle讀取(Shuffle Fetch)方面,大多數場景Spark並不在Reduce端做歸併和排序,而是採用Aggregator機制。Aggregator本質是個HashMap,其中每個元素都是<K,V>形式。

ps:以詞頻統計為例,它會將從Map端拉取到的每一個(key,value),更新或插入到HashMap中。若在HashMap中沒有查詢到這個key,則把這個(key,value)插入其中;若找到這個key,則把value的值累加到V上去。這樣就不需要預先把所有的(key,value)進行歸併和排序,而是來一個處理一個,避免外部排序這一步驟。

③、窄依賴寬依賴

以是否包含Shuffle操作為判斷依據,RDD中的依賴關係可以分為窄依賴與寬依賴,區別如下

窄依賴:一個父RDD的分割槽對應一個子RDD的分割槽,或者多個父RDD的分割槽對應一個子RDD的分割槽。典型操作包括map/filter/union等,不會包含Shuffle操作

寬依賴:一個父RDD的一個分割槽對應一個子RDD的多個分割槽。典型操作包括groupByKey/sortByKey等,通常包含Shuffle操作

ps:對於join操作,視情況而定,如上圖左側進行協同劃分,資料窄依賴。如上圖右側做非協同劃分,屬於寬依賴。

④、階段劃分

Spark根據DAG圖中的RDD依賴關係,把一個作業分成多個階段。參考下圖例子過程:

Stage2為窄依賴,可以把多個fork/join合併為一個,不但減少了大量的全域性路障,而且無需儲存很多中間結果RDD,可以極大提高效能,該過程叫流水線優化(Pipeline)


學習交流,有任何問題還請隨時評論指出交流。

相關文章