MapReduce中的Shuffle
在MapReduce框架中,shuffle是連接Map和Reduce之間的橋梁,Map的輸出要用到Reduce中必須經過shuffle這個環節,shuffle的性能高低直接影響了整個程序的性能和吞吐量。
Shuffle是MapReduce框架中的一個特定的phase,介于Map phase和Reduce phase之間,當Map的輸出結果要被Reduce使用時,輸出結果需要按key哈希,并且分發到每一個Reducer上去,這個過程就是shuffle。由于shuffle涉及到了磁盤的讀寫和網絡的傳輸,因此shuffle性能的高低直接影響到了整個程序的運行效率。
下圖描述了MapReduce算法的整個流程,其中shuffle phase是介于Map phase和Reduce phase之間:

在Hadoop, 在mapper端每次當memory buffer中的數據快滿的時候, 先將memory中的數據, 按partition進行劃分, 然后各自存成小文件, 這樣當buffer不斷的spill的時候, 就會產生大量的小文件。
所以Hadoop后面直到reduce之前做的所有的事情其實就是不斷的merge, 基于文件的多路并歸排序,在map端的將相同partition的merge到一起, 在reduce端, 把從mapper端copy來的數據文件進行merge, 以用于最終的reduce
多路歸并排序, 達到兩個目的。
merge, 把相同key的value都放到一個arraylist里面;sort, 最終的結果是按key排序的。
這個方案擴展性很好, 面對大數據也沒有問題, 當然問題在效率, 畢竟需要多次進行基于文件的多路歸并排序,多輪的和磁盤進行數據讀寫。

Spark的Shuffle機制
Spark中的Shuffle是把一組無規則的數據盡量轉換成一組具有一定規則的數據。
Spark計算模型是在分布式的環境下計算的,這就不可能在單進程空間中容納所有的計算數據來進行計算,這樣數據就按照Key進行分區,分配成一塊一塊的小分區,打散分布在集群的各個進程的內存空間中,并不是所有計算算子都滿足于按照一種方式分區進行計算。
當需要對數據進行排序存儲時,就有了重新按照一定的規則對數據重新分區的必要,Shuffle就是包裹在各種需要重分區的算子之下的一個對數據進行重新組合的過程。在邏輯上還可以這樣理解:由于重新分區需要知道分區規則,而分區規則按照數據的Key通過映射函數(Hash或者Range等)進行劃分,由數據確定出Key的過程就是Map過程,同時Map過程也可以做數據處理,例如,在Join算法中有一個很經典的算法叫Map Side Join,就是確定數據該放到哪個分區的邏輯定義階段。Shuffle將數據進行收集分配到指定Reduce分區,Reduce階段根據函數對相應的分區做Reduce所需的函數處理。
Spark中Shuffle的流程

- 首先每一個Mapper會根據Reducer的數量創建出相應的bucket,bucket的數量是M×R,其中M是Map的個數,R是Reduce的個數。
- 其次Mapper產生的結果會根據設置的partition算法填充到每個bucket中去。這里的partition算法是可以自定義的,當然默認的算法是根據key哈希到不同的bucket中去。
- 當Reducer啟動時,它會根據自己task的id和所依賴的Mapper的id從遠端或是本地的block manager中取得相應的bucket作為Reducer的輸入進行處理。
這里的bucket是一個抽象概念,在實現中每個bucket可以對應一個文件,可以對應文件的一部分或是其他等。
轉載請注明作者Jason Ding及其出處
GitCafe博客主頁(http://jasonding1354.gitcafe.io/)
Github博客主頁(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
簡書主頁(http://www.lxweimin.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354進入我的博客主頁