一、概述
理解Hadoop的Shuffle過程是一個大數據工程師必須的,筆者自己將學習筆記記錄下來,以便以后方便復習查看。
二、
MapReduce確保每個reducer的輸入都是按鍵排序的。系統執行排序、將map輸出作為輸入傳給reducer的過程稱為Shuffle。
2.1 map端
map函數開始產生輸出時,利用緩沖的方式寫到內存並排序具體分一下幾個步驟。
1.map數據分片:把輸入數據源進行分片,根據分片來決定有多少個map,每個map任務都有一個環形內存緩沖區用於存儲任務輸出,默認情況下緩沖區大小為100MB,可通過mapreduce.task.io.sort.mb來調整。
2.map排序:當map緩沖區大小達到閾值時(mapreduce.map.sort.spill.percent),就會將內存的數據溢寫到磁盤,根據reducer的來划分成相應的partition,在內存中按鍵值進行排序,如果有combiner函數,在排序后就會應用,排序后寫入分區磁盤文件中。溢寫的過程中,map會阻塞直到寫磁盤過程完成。每次內存緩沖區到達溢出閾值,就會新建一個溢出文件件,在map寫完最后一個輸出記錄之后,會有幾個溢出文件,在任務完成之前溢出文件會被合並成一個已分區且已經排序的輸出文件。mapreduce.task.io.sort.factor控制着一次最多能合並多少溜,默認10。mapreduce.map.output.compress進行壓縮,提高寫磁盤速度。
2.2reduce端
1.reduce復制:reducer通過http得到輸出文件的分區,用於文件分區的工作線程數量由任務的mapreduce.shuffle.max.threads屬性控制。每個map任務的完成時間不同,在每個任務完成時,reduce任務就開始復制其輸出,這就是reduce任務的復制階段,reduce的復制線程數量mapreduce.reduce.shuffle.parallelcopies決定。
復制詳解:如果map輸出很小,會被復制到reduce任務JVM的內存,否則輸出被復制到磁盤。如果內存緩沖區達到閾值大小(mapreduce.reduce.shuffle.merge.percent)或達到map輸出閾值(mapreduce.reduce.merge.inmem.threshold),則合並溢出寫到磁盤中,如果指定combiner,則在合並期間運行它。隨着磁盤上副本增多,后台線程會將他們合並為更大的,排序的文件。
2.reduce合並排序:這個階段合並map輸出,維持其順序排序,這是循環進行的,如果有50個map輸出,合並因子是10(mapreduce.task.io.sort.factor),合並將進行5次,最后有5個中間文件。
3.reduce:直接把數據輸入reduce函數,從而省略了一次磁盤的往返行程。

至此mapreduce過程完畢,具體參考Hadoop權威指南第四版。
