MapReduce Shuffle 和 Spark Shuffle 詳解

Shuffle簡介

shuffle的本意是洗牌、混洗的意思,把一組有規則的數據儘量打亂成無規則的數據。而在MapReduce中,Shuffle更像是洗牌的逆過程,指的是將map端的無規則輸出按指定的規則“打亂”成具有一定規則的數據,以便reduce端接收處理。其在MapReduce中所處的工作階段是map輸出後到reduce接收前,具體可以分爲map端和reduce端前後兩個部分。
在shuffle之前,也就是在map階段,MapReduce會對要處理的數據進行分片(split)操作,爲每一個分片分配一個MapTask任務。接下來map會對每一個分片中的每一行數據進行處理得到鍵值對(key,value)此時得到的鍵值對又叫做“中間結果”。此後便進入reduce階段,由此可以看出Shuffle階段的作用是處理“中間結果”。
由於Shuffle涉及到了磁盤的讀寫和網絡的傳輸,因此Shuffle性能的高低直接影響到了整個程序的運行效率。

MapReduce Shuffle

Map端的shuffle

下圖是MapReduce Shuffle的官方流程:
在這裏插入圖片描述
因爲頻繁的磁盤I/O操作會嚴重的降低效率,因此“中間結果”不會立馬寫入磁盤,而是優先存儲到map節點的“環形內存緩衝區”,在寫入的過程中進行分區(partition),也就是對於每個鍵值對來說,都增加了一個partition屬性值,然後連同鍵值對一起序列化成字節數組寫入到緩衝區(緩衝區採用的就是字節數組,默認大小爲100M)。
當寫入的數據量達到預先設置的闕值後便會啓動溢寫出線程將緩衝區中的那部分數據溢出寫(spill)到磁盤的臨時文件中,並在寫入前根據key進行排序(sort)和合並(combine,可選操作)。
溢出寫過程按輪詢方式將緩衝區中的內容寫到mapreduce.cluster.local.dir屬性指定的本地目錄中。當整個map任務完成溢出寫後,會對磁盤中這個map任務產生的所有臨時文件(spill文件)進行歸併(merge)操作生成最終的正式輸出文件,此時的歸併是將所有spill文件中的相同partition合併到一起,並對各個partition中的數據再進行一次排序(sort),生成key和對應的value-list,文件歸併時,如果溢寫文件數量超過參數min.num.spills.for.combine的值(默認爲3)時,可以再次進行合併。
至此map端的工作已經全部結束,最終生成的文件也會存儲在TaskTracker能夠訪問的位置。每個reduce task不間斷的通過RPC從JobTracker那裏獲取map task是否完成的信息,如果得到的信息是map task已經完成,那麼Shuffle的後半段開始啓動。

Reduce端的shuffle

當mapreduce任務提交後,reduce task就不斷通過RPC從JobTracker那裏獲取map task是否完成的信息,如果獲知某臺TaskTracker上的map task執行完成,Shuffle的後半段過程就開始啓動。Reduce端的shuffle主要包括三個階段,copy、merge和reduce。
每個reduce task負責處理一個分區的文件,以下是reduce task的處理流程:
在這裏插入圖片描述

  • reduce task從每個map task的結果文件中拉取對應分區的數據。因爲數據在map階段已經是分好區了,並且會有一個額外的索引文件記錄每個分區的起始偏移量。所以reduce task取數的時候直接根據偏移量去拉取數據就ok。
  • reduce task從每個map task拉取分區數據的時候會進行再次合併,排序,按照自定義的reducer的邏輯代碼去處理。
  • 最後就是Reduce過程了,在這個過程中產生了最終的輸出結果,並將其寫到HDFS上。

爲什麼要排序

key存在combine操作,排序之後相同的key放到一塊顯然方便做合併操作。
reduce task是按key去處理數據的。 如果沒有排序那必須從所有數據中把當前相同key的所有value數據拿出來,然後進行reduce邏輯處理。顯然每個key到這個邏輯都需要做一次全量數據掃描,影響性能,有了排序很方便的得到一個key對於的value集合。
reduce task按key去處理數據時,如果key按順序排序,那麼reduce task就按key順序去讀取,顯然當讀到的key是文件末尾的key那麼就標誌數據處理完畢。如果沒有排序那還得有其他邏輯來記錄哪些key處理完了,哪些key沒有處理完。
雖有千萬種理由需要這麼做,但是很耗資源,並且像排序其實我們有些業務並不需要排序。

爲什麼要文件合併

因爲內存放不下就會溢寫文件,就會發生多次溢寫,形成很多小文件,如果不合並,顯然會小文件氾濫,集羣需要資源開銷去管理這些小文件數據。
任務去讀取文件的數增多,打開的文件句柄數也會增多。
mapreduce是全局有序。單個文件有序,不代表全局有序,只有把小文件合併一起排序纔會全局有序。

Spark Shuffle

  • Shuffle 過程本質上都是將 Map 端獲得的數據使用分區器進行劃分,並將數據發送給對應的 Reducer 的過程。
  • Shuffle作爲處理連接map端和reduce端的樞紐,其shuffle的性能高低直接影響了整個程序的性能和吞吐量。map端的shuffle一般爲shuffle的Write階段,reduce端的shuffle一般爲shuffle的read階段。Hadoop和spark的shuffle在實現上面存在很大的不同,spark的shuffle分爲兩種實現,分別爲HashShuffle和SortShuffle。
  • HashShuffle又分爲普通機制和合並機制,普通機制因爲其會產生MR個數的巨量磁盤小文件而產生大量性能低下的Io操作,從而性能較低,因爲其巨量的磁盤小文件還可能導致OOM,HashShuffle的合併機制通過重複利用buffer從而將磁盤小文件的數量降低到CoreR個,但是當Reducer端的並行任務或者是數據分片過多的時候,依然會產生大量的磁盤小文件。
  • SortShuffle也分爲普通機制和bypass機制,普通機制在內存數據結構(默認爲5M)完成排序,會產生2M個磁盤小文件。而當shuffle
    map task數量小於spark.shuffle.sort.bypassMergeThreshold參數的值。或者算子不是聚合類的shuffle算子(比如reduceByKey)的時候會觸發SortShuffle的bypass機制,SortShuffle的bypass機制不會進行排序,極大的提高了其性能。
  • 在Spark1.2以前,默認的shuffle計算引擎是HashShuffleManager,因爲HashShuffleManager會產生大量的磁盤小文件而性能低下,在Spark
    1.2以後的版本中,默認的ShuffleManager改成了SortShuffleManager。
  • SortShuffleManager相較於HashShuffleManager來說,有了一定的改進。主要就在於,每個Task在進行shuffle操作時,雖然也會產生較多的臨時磁盤文件,但是最後會將所有的臨時文件合併(merge)成一個磁盤文件,因此每個Task就只有一個磁盤文件。在下一個stage的shuffle read task拉取自己的數據時,只要根據索引讀取每個磁盤文件中的部分數據即可。

Spark與MapReduce Shuffle的異同

  • 從整體功能上看,兩者並沒有大的差別。 都是將 mapper(Spark 裏是 ShuffleMapTask)的輸出進行partition,不同的 partition 送到不同的 reducer(Spark 裏 reducer 可能是下一個 stage 裏的ShuffleMapTask,也可能是 ResultTask)。Reducer 以內存作緩衝區,邊 shuffle 邊 aggregate 數據,等到數據 aggregate 好以後進行 reduce(Spark 裏可能是後續的一系列操作)。
  • 從流程的上看,兩者差別不小。 Hadoop MapReduce 是 sort-based,進入 combine和 reduce的records 必須先 sort。這樣的好處在於combine/reduce可以處理大規模的數據,因爲其輸入數據可以通過外排得到(mapper 對每段數據先做排序,reducer 的shuffle 對排好序的每段數據做歸併)。以前 Spark 默認選擇的是 hash-based,通常使用 HashMap 來對shuffle 來的數據進行合併,不會對數據進行提前排序。如果用戶需要經過排序的數據,那麼需要自己調用類似sortByKey的操作。在Spark 1.2之後,sort-based變爲默認的Shuffle實現。
  • 從流程實現角度來看,兩者也有不少差別。 Hadoop MapReduce 將處理流程劃分出明顯的幾個階段:map, spill, merge, shuffle, sort, reduce等。每個階段各司其職,可以按照過程式的編程思想來逐一實現每個階段的功能。在Spark 中,沒有這樣功能明確的階段,只有不同的 stage 和一系列的 transformation,所以 spill, merge,aggregate 等操作需要蘊含在 transformation中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章