組成部分緩存
Shuffle階段分爲兩部分:Map端和Reduce端。spa
Sort階段就是對Map端輸出的key進行排序。線程
第一部分:Map端Shuffle排序
對於輸入文件,會進行分片,對於一個split,有一個map任務進行處理,每一個Map在內存中都有一個緩存區,map的輸出結果會先放到這個緩衝區中,在緩衝區中,會進行預排序(即sort和comibner),以提升效率。索引
緩衝區默認大小是100MB(能夠經過io.sort.mb屬性更改大小),當緩衝區中的數據達到特定的閾值(io.sort.mb * io.sort.spill.percent,其中io.sort.spill.percent默認是0.80)時,系統會啓動一個後臺線程把緩衝區的內容spill(溢寫)到磁盤。溢出到磁盤的一個臨時文件中,即80%的內容成爲一個臨時文件。當這80%的內容溢出時,map會繼續向剩餘的20%緩衝區中輸出。內存
spill線程在把緩衝區中的數據寫到磁盤前,會進行一個二次快速排序,首先根據數據所屬的Partition排序,而後每一個Partition中再按Key排序。輸出包括一個索引文件和數據文件。若是設定了Combiner,將在排序輸出的基礎上進行。it
Comibner就是一個Mini Reducer,在執行Map任務的節點自己運行,對Map的輸出作一次簡單Reduce,使得Map'de輸出更緊湊,更少的數據會被寫入磁盤和傳送到Reduce端。io
一個Map任務會產生多個spill文件,在Map任務完成前,全部的spill文件將會歸併排序爲一個索引文件和數據文件。當spill文件歸併完成後,Map將刪除全部的臨時文件,並告知TaskTracker任務已完成。效率
對寫入到磁盤的數據能夠選擇採起壓縮的方式,若是須要壓縮,則須要設置mapred.compress.map.output爲true。後臺
還有一個Partition的概念,一個臨時文件是進行了分區的,而且分區的數量由reduce的數量決定,不一樣的分區傳給不一樣的reduce。
第二部分:Reduce端Shuffle
Reduce端經過HTTP獲取Map端的數據,只要有一個map任務完成,Reduce任務就開始複製它的輸出,這稱爲copy階段。
JobTracker知道Map輸出與TaskTracker的映射關係,Reduce端有一個線程間歇地向JobTracker詢問Map輸出的地址,直到把全部的數據都獲取到。
若是map輸出比較小,他們被複制到Reduce的內存中,若是緩衝區空間不足,會被複制到磁盤上。複製的數據放在磁盤上,後臺線程會進行歸併爲更大的排序文件,對於壓縮文件,系統會自動解壓到內存方便歸併。
當全部的Map輸出被複制後,Reduce任務進入排序階段(確切的說是歸併階段),這個過程會重複屢次。Merge有三種形式:內存到內存,內存到磁盤,磁盤到磁盤。
內存到內存默認不啓用;內存到磁盤的方式也會產生溢寫,若是設置了Combiner,此時也會啓用,在磁盤上生成多個溢寫文件;磁盤到磁盤會生成一個最終的文件做爲Reduce的輸入。