MapReduce的Shuffle過程詳細理解

Map端

Map執行完,開始輸出,也就是寫入到環形內存緩衝區,輸出時按照輸出的key進行分區(Partition,分區方式默認按照key的hash值對reducer個數取模)。數據在環形內存緩衝區,超過閾值(默認100MB,可mapreduce.task.io.sort.mb來設定,是指一個task的,整個工作叫job,單獨的map和reduce叫task,超過閾值表示超過80%,可mapreduce.map.sort.spill.percent設置)後執行溢出寫,寫之前會對區內進行排序,如果定義了Combiner(沒有定義的應該放入List中)則排序後還要調用Combiner合併(類似reduce)。一個map任務每次溢出寫會寫入一個單獨文件,如果map輸出結果很大會產生多個文件,在該map任務結束前(就是計算完了,整個map還沒算完),會合並(merge)這些spill文件(可通過mapreduce.task.io.sort.factor設置一次合併的文件個數,默認爲10,如果spill過多可調大該值來減少操作磁盤的次數,提高性能),合併時如果定義了Combiner(和上面的Combiner是一個類)會進行Combine。最終一個Map會生成一個文件。輸出到磁盤的過程中可設置壓縮(mapreduce.map.output.compress爲true表示壓縮)。

Reduce端

Reduce的Shuffle階段分爲複製(fetch)和排序(sort)過程。Map任務完成會通過心跳通知Application Master,Reduce端會有一個線程查詢Application Master,只要有Map完成Reduce就可以開啓複製(通過HTTP請求Map所在的TaskTracker獲取其輸出文件),複製過程是多線程併發(通過mapreduce.reduce.shuffle.parallelcopies設置線程個數,默認5)。Reduce複製的數據先寫入到reduce任務的JVM內存,當超過一定閾值(通過mapreduce.reduce.shuffle.input.buffer.percent設置大小,默認0.7,也就是0.7*maxHeap of reduce task,一個reduce任務堆內存的70%,因爲Reduce的Shuffle階段Reduce任務不運行,所以大部分堆內存都給Shuffle使用)會刷寫(類似Spill)到磁盤,這裏和Map類似不是到最大值才刷寫,而是達到一定比例(可通過mapreduce.reduce.shuffle.merge.percent設置比例,默認0.66)開始刷寫,也有人說可通過mapreduce.reduce.merge.inmem.threshold設定文件個數(默認1000),超過個數也執行刷寫。刷寫時也執行類似Map任務的Spill的Sort和Combiner。複製完成後,刷寫的文件可能多個(內存中的都要刷寫到磁盤中),這時需要合併(merge,mapreduce.task.io.sort.factor參數也會影響這裏),如果定義了Combiner函數也會調用進行Combine,最後一次合併(merge)後的數據不再寫入文件,直接作爲Reduce任務的輸入。其實Shuffle過程是從Map和Reduce過程分出來的。

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