好程序員大數據學習路線分享MapReduce全過程解析,移動數據與移動計算
在學習大數據的時候接觸了移動數據和移動計算這兩種聯繫緊密而又有很大不一樣的概念,其中移動計算也叫作本地計算。
在之前的數據處理中時使用的移動數據,其實就是將須要處理的數據傳輸到存放不一樣處理數據方式邏輯的各個節點上。這樣作的效率很低,特別是大數據中的數據量是很大的,至少都是GB以上,更大的是TB、PB甚至更大,並且磁盤I/O、網絡I/O的效率是很低的,這樣處理起來就須要很長的時間,遠遠不能知足咱們的要求。而移動計算就出現了。
移動計算,也叫作本地計算,是數據就存放在節點上再也不變更,而是將處理邏輯程序傳輸到各個數據節點上。因爲處理程序的大小確定不會特別的大,這樣就能夠實現很快將程序傳輸到存放數據的各個節點上去,而後本地執行處理數據,效率高。如今的大數據處理技術都是採用這種方式。程序員
言簡意賅的說:
Map階段:
一、Read:讀取數據源,將數據進行filter成一個個的K/V
二、Map:在map函數中,處理解析的K/V,併產生新的K/V
三、Collect:輸出結果,存於環形內緩衝區
四、Spill:內存區滿,數據寫到本地磁盤,並生產臨時文件
五、Combine:合併臨時文件,確保生產一個數據文件算法
Reduce階段:
一、Shuffle:Copy階段,Reduce Task到各個Map Task遠程複製一分數據,針對某一份數據,二、若其大小超過必定閥值,則寫磁盤;不然放到內存
三、Merge:合併內存和磁盤上的文件,防止內存佔用過多或磁盤文件過多
四、Sort:Map Task階段進行局部排序,Reduce Task階段進行一次歸併排序
五、Reduce:將數據給reduce函數
六、Write:reduce函數將其計算的結果寫到HDFS上緩存
深度解析的說:
MapTask階段
(1)Read階段:MapTask經過用戶編寫的RecordReader,從輸入InputSplit中解析出一個個key/value。
(2)Map階段:該節點主要是將解析出的key/value交給用戶編寫map()函數處理,併產生一系列新的key/value。
(3)Collect收集階段:在用戶編寫map()函數中,當數據處理完成後,通常會調用 OutputCollector.collect()輸出結果。在該函數內部,它會將生成的key/value分區(調用 Partitioner),並寫入一個環形內存緩衝區中。
(4)Spill階段:即「溢寫」,當環形緩衝區滿後,MapReduce 會將數據寫到本地磁盤上,生成一個臨時文件。須要注意的是,將數據寫入本地磁盤以前,先要對數據進行一次本地排序,並在必要時對數據進行合併、壓縮等操做。網絡
溢寫階段詳情:
步驟1:利用快速排序算法對緩存區內的數據進行排序,排序方式是,先按照分區編號partition進行排序,而後按照key進行排序。這樣,通過排序後,數據以分區爲單位彙集在一塊兒,且同一分區內全部數據按照key有序。
步驟2:按照分區編號由小到大依次將每一個分區中的數據寫入任務工做目錄下的臨時文件output/spillN.out(N表示當前溢寫次數)中。若是用戶設置了Combiner,則寫入文件以前,對每一個分區中的數據進行一次彙集操做。
步驟3:將分區數據的元信息寫到內存索引數據結構SpillRecord中,其中每一個分區的元信息包括在臨時文件中的偏移量、壓縮前數據大小和壓縮後數據大小。若是當前內存索引大小超過1MB,則將內存索引寫到文件output/spillN.out.index中。
(5)Combine階段:當全部數據處理完成後,MapTask對全部臨時文件進行一次合併,以確保最終只會生成一個數據文件。當全部數據處理完後,MapTask會將全部臨時文件合併成一個大文件,並保存到文件output/file.out中,同時生成相應的索引文件output/file.out.index。在進行文件合併過程當中,MapTask以分區爲單位進行合併。對於某個分區,它將採用多輪遞歸合併的方式。每輪合併io.sort.factor(默認100)個文件,並將產生的文件從新加入待合併列表中,對文件排序後,重複以上過程,直到最終獲得一個大文件。讓每一個MapTask最終只生成一個數據文件,可避免同時打開大量文件和同時讀取大量小文件產生的隨機讀取帶來的開銷。信息包括在臨時文件中的偏移量、壓縮前數據大小和壓縮後數據大小。若是當前內存索引大小超過1MB,則將內存索引寫到文件output/spillN.out.index中。
Shuffle階段(map端的輸出到reduce的輸入)
1)maptask收集咱們的map()方法輸出的kv對,放到內存緩衝區中
2)從內存緩衝區不斷溢出本地磁盤文件,可能會溢出多個文件
3)多個溢出文件會被合併成大的溢出文件
4)在溢出過程當中,及合併的過程當中,都要調用partitioner進行分區和針對key進行排序
5)reducetask根據本身的分區號,去各個maptask機器上取相應的結果分區數據
6)reducetask會取到同一個分區的來自不一樣maptask的結果文件,reducetask會將這些文件再進行合併(歸併排序)
7)合併成大文件後,shuffle的過程也就結束了,後面進入reducetask的邏輯運算過程(從文件中取出一個一個的鍵值對group,調用用戶自定義的reduce()方法)
3)注意Shuffle中的緩衝區大小會影響到mapreduce程序的執行效率,原則上說,緩衝區越大,磁盤io的次數越少,執行速度就越快。緩衝區的大小能夠經過參數調整,參數:io.sort.mb默認100M。數據結構
ReduceTask階段
(1)Copy階段:ReduceTask從各個MapTask上遠程拷貝一片數據,並針對某一片數據,若是其大小超過必定閾值,則寫到磁盤上,不然直接放到內存中。
(2)Merge階段:在遠程拷貝數據的同時,ReduceTask啓動了兩個後臺線程對內存和磁盤上的文件進行合併,以防止內存使用過多或磁盤上文件過多。
(3)Sort階段:按照MapReduce語義,用戶編寫reduce()函數輸入數據是按key進行彙集的一組數據。爲了將key相同的數據聚在一塊兒,Hadoop採用了基於排序的策略。因爲各個MapTask已經實現對本身的處理結果進行了局部排序,所以,ReduceTask只需對全部數據進行一次歸併排序便可。
(4)Reduce階段:reduce()函數將計算結果寫到HDFS上。函數