徹底解惑MapReduce核心shuffle的執行流程及MapReduce調優前瞻

 以處理text文件爲例

map端

map端:
    1、MRApplicationMaster啓動maptask,並分配其一個編號,maptask根據編號尋找對應的存儲文件位
       置信息及切片長度的數據切片,默認數據切片對應的文件大小與blocksize大小一致。然後maptask
       再根據數據切片尋找對應數據文件信息。然後maptask會通
       org.apache.hadoop.mapreduce.InputFormat接口的TextInputFormat實現類的
       createRecordReader()方法創建LineRecordReader對象,通過該對象的nextKey()和
       nextValue()方法從hdfs上逐行讀取數據文件內容,key爲該行數據的偏移量,value爲該行數據。
       再交由mapper類進行數據的處理。
       
    2、mapper類對數據處理完後會調用Context對象的write()方法將數據寫出,而
       org.apache.hadoop.mapred.OutputCollector類則負責將這些數據收集放入環形緩衝區中。數據    
       進入緩衝區前會通過org.apache.hadoop.mapred.Partitioner類進行分區,分區方式爲對key取
       hash再對reduce數量取模。這就使得一個分區對應於一個reducetask。分區之後數據文件文件會序  
       列化成字節數組,進入環形緩衝區中。每個maptask都有一個環形緩衝區,默認大小爲100MB,環形緩
       衝區本質上就是一個字節數組。

    3、當環形緩衝區達到80%滿的時候,啓動一個單獨的Spiller線程鎖定環形緩衝區這80%的內存,進行溢
       寫操作,其餘20%的內存仍然可以接收數據的輸入。每次溢寫被執行後,都會形成一個小文件,當數據
       寫入影響到了溢寫時,環形緩衝區的數據輸入會阻塞。在溢寫真正被觸發執行前,會先通過
       org.apache.hadoop.util.QuickSort類先對環形緩衝區中的數據進行一個二次快速排序,先按分
       區排,再按key排,排序結束後單個分區內數據按key有序。

    4-a、如果設定了combiner,並且當前maptask已經溢寫形成的小文件數目不小於3,則觸發combiner,     
         combiner會對環形緩衝區內的數據做一次按key聚合操作,減少溢寫到磁盤的數據量(不改變溢寫的
         總文件數,這點要理解)。每一次溢寫都是按分區號逐個進行的,溢寫操作會直到最後一份數據溢寫
         完成後結束。
    5-a、整個maptask的所有溢寫操作完成後會對當前maptask溢寫產生的所有小文件執行merge操作,將其
         merge成一個大的數據文件和索引文件。整個merge過程用到了外部排序和歸併排序兩種排序算法,
         merge結束,該數據文件內每個分區內的數據都有序排列。然後刪除所有spill中間文件後,
         當前maptask結束。
         
    4-b、如果設定了combiner,並且當前maptask溢寫形成的小文件數目小於3,則直接執行溢寫操作,溢
         寫按分區號逐個進行,溢寫操作會直到最後一份數據溢寫完成後結束。
    5-b、整個maptask的所有溢寫操作完成後會對當前maptask溢寫產生的所有小文件執行merge操作,將其
         merge成一個大的數據文件和索引文件。整個merge過程用到了外部排序和歸併排序兩種排序算法,
         merge結束,該數據文件內每個分區內的數據都有序排列。然後刪除所有spill中間文件後進入
         combiner階段,combiner會對數據文件內的每一個分區數據做一次按key聚合操作,減少輸入到
         reduce端的數據量。combiner完成則當前maptask結束。


注意事項:
    merge前,A小文件的1號分區有{a:2},B小文件的1號分區有{a:5},merge之後就成了C大文件1號分區{a:[2,5]}。
    merge不是一蹴而就的,每次只merge10個文件,由mapreduce.task.io.sort.factor控制。
    combiner前,A小文件的1號分區有{a:1},{a:4},B小文件的1號分區有{b:1},{b:3},combiner之後就形成了A小文件的1號分區有{a:5},B小文件的1號分區有{b:4}。

####以上注意事項請好好理解

####集羣很繁忙的情況下設置了combiner,也可能不生效。
#####所有溢寫小文件和merge後的大文件都是senquence文件

 reduce端

reduce端:
    1、MRApplicationMaster啓動reducetask,並給其分配一個編號,reducetask根據編號通過http協
       議拉取對應的分區數據,該分區數據可能位於所有的maptask中,所以reducetask會啓動多個線程拉
       取數據,最多5個,由參數mapreduce.reduce.shuffle.parallelcopies控制。每一個
       reducetask都有一個內存緩衝區,當在某個map端拉取的數據大小小於內存緩衝區大小的25%,則進
       入內存緩衝區中,否則直接進入磁盤。
    
    2、當內存緩衝區的數據文件達到1000個(mapreduce.reduce.merge.inmem.threshold)或者內存緩衝
       區的數據佔用內存比達到66%(mapreduce.reduce.shuffle.merge.percent)的時候,會在內存中
       執行merge操作。如果設定了combiner,則merge過程中也會執行combiner操作,這兩個操作結束,
       內存緩衝區中的數據溢寫到磁盤形成小文件,溢寫的次數可能很多次,且有一些maptask拉取過來的文
       件不經過內存緩衝區直接存在磁盤,所以磁盤上的小文件可能有很多個。由由於merge過程會使用歸併
       排序,所以單個溢寫小文件中的數據也是有序排列的。
    
    3、噹噹前reducetask的所有數據全部拉取並在磁盤形成小文件後,會將所有的小文件merge成一個大文
       件,merge過程會使用歸併排序,所以形成的大文件也是有序的。整個merge過程不是一蹴而就的,每
       次merge只會合併10個文件,由mapreduce.task.io.sort.factor控制,假設有50個文件,則要執
       行6次merge。
    

    4、merge之後Reducer類通過迭代器獲取數據的key-value鍵值對,知道一個key對應的所有鍵值對全部    
       獲取玩會執行reduce方法處理,處理結束通過Context對象的write方法將處理結果寫出,但它並非
       直接寫出,而是會判斷配置文件中配置的輸出文件類型後再寫出,如果沒有配置,則reducetask會
       通過org.apache.hadoop.mapreduce.InputFormat接口的TextInputFormat實現類的
       getRecordWriter()方法創建LineRecordWriter對象,通過該對象的write()方法將該key對應
       數據寫出到hdfs的結果文件中。則然後處理下一個key對應的數據,直到當前reducetask的所有數據
       全部被處理完成且正確輸出後,當前reducetask結束。
        
        #####輸出到hdfs上時,每一對key-value對應一行數據,tab鍵分隔。
        #####如果當前reducetask的編號爲0,則產生的輸出文件就爲part-r-000000,爲1,則產生的輸出文件就爲part-r-000001
        #####過程中涉及到兩次merge,這種情況發生在maptask特別多的情況下。在極少maptask的情況下,設甚至是可以沒有merge的。





#####所有溢寫小文件和merge後的大文件都是senquence文件


mapreduce調優前瞻

縱觀整個流程,你能夠更改的(非參數層面):

1、Mapper類
2、maptask對hdfs上文件的讀取
3、進入環形緩衝區前的分區
4、combiner
5、reducetask對merge後大文件的讀取
6、Reducer類
7、reducetask對hdfs的文件輸出


非參數層面的mapreduce優化可以對這七個層面動刀。




     
 

 

 

 

 

 

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