其他更多java基礎文章:
java基礎學習(目錄)
學習資料:
詳細講解MapReduce過程(整理補充)
MapReduce原理
1.在客戶端啟動一個作業。
2.向JobTracker請求一個Job ID。
3.將執行作業所需要的資原始檔複製到HDFS上,包括MapReduce程式打包的JAR檔案、配置檔案和客戶端計算所得的輸入劃分資訊。這些檔案都存放在JobTracker專門為該作業建立的資料夾中。資料夾名為該作業的Job ID。JAR檔案預設會有10個副本(mapred.submit.replication屬性控制);輸入劃分資訊告訴了JobTracker應該為這個作業啟動多少個map任務等資訊。
4.JobTracker接收到作業後,將其放在一個作業佇列裡,等待作業排程器對其進行排程,當作業排程器根據自己的排程演算法排程到該作業時,會根據輸入劃分資訊為每個劃分建立一個map任務,並將map任務分配給TaskTracker執行。對於map和reduce任務,TaskTracker根據主機核的數量和記憶體的大小有固定數量的map槽和reduce槽。這裡需要強調的是:map任務不是隨隨便便地分配給某個TaskTracker的,這裡有個概念叫:資料本地化(Data-Local)。意思是:將map任務分配給含有該map處理的資料塊的TaskTracker上,同時將程式JAR包複製到該TaskTracker上來執行,這叫“運算移動,資料不移動”。而分配reduce任務時並不考慮資料本地化。
5.TaskTracker每隔一段時間會給JobTracker傳送一個心跳,告訴JobTracker它依然在執行,同時心跳中還攜帶著很多的資訊,比如當前map任務完成的進度等資訊。當JobTracker收到作業的最後一個任務完成資訊時,便把該作業設定成“成功”。當JobClient查詢狀態時,它將得知任務已完成,便顯示一條訊息給使用者。
MapReduce 任務中 Shuffle 和排序的過程
流程分析:
- Map 端:
-
每個輸入分片會讓一個 map 任務來處理,預設情況下,以 HDFS 的一個塊的大小(預設為 64M)為一個分片,當然我們也可以設定塊的大小。 map 輸出的結果會暫且放在一個環形記憶體緩衝區中(該緩衝區的大小預設為 100M,由 io.sort.mb 屬性控制),當該緩衝區快要溢位時(預設為緩衝區大小的 80%,由 io.sort.spill.percent 屬性控制),會在本地檔案系統中建立一個溢位檔案,將該緩衝區中的資料寫入這個檔案。
-
在寫入磁碟之前,執行緒首先根據 reduce 任務的數目將資料劃分為相同數目的分割槽,也就是一個 reduce 任務對應一個分割槽的資料。分割槽就是給資料打一個標籤,讓它被某個固定的 reduce 執行,這樣做是為了避免有些 reduce 任務分配到大量資料,而有些reduce 任務卻分到很少資料,甚至沒有分到資料的尷尬局面。其實分割槽就是對資料進 行 hash 的過程。然後對每個分割槽中的資料進行排序,如果此時設定了 Combiner,將排序後的結果進行 combine 操作,這樣做的目的是讓儘可能少的資料寫入到磁碟。
-
當 map 任務輸出最後一個記錄時,可能會有很多的溢位檔案,這時需要將這些檔案合併。合併的過程中會不斷地進行排序和 combine 操作,目的有兩個: 1)儘量減少每次寫入磁碟的資料量;2)儘量減少下一複製階段網路傳輸的資料量。最後合併成了一個已分割槽且已排序的檔案。為了減少網路傳輸的資料量,這裡可以將資料壓縮,只要將mapred.compress.map.out 設定為 true 就可以了。
-
將分割槽中的資料拷貝給相對應的 reduce 任務。分割槽中的資料怎麼知道它對應的 reduce 是哪個呢?其實 map 任務一直和其父程式 TaskTracker 保持聯絡,而 TaskTracker 又一 直和 JobTracker 保持心跳。所以 JobTracker 中儲存了整個叢集中的巨集觀資訊。只要 reduce 任務向 JobTracker 獲取對應的 map 輸出位置就 ok 了哦。 到這裡, map 端就分析完了。那到底什麼是 Shuffle 呢? Shuffle 的中文意思是“洗 牌”,一個 map 產生的資料,結果通過 hash 過程分割槽卻分配給了不同的 reduce 任務,就 是一個對資料洗牌的過程。
- Reduce 端:
-
每個map任務的完成時間可能不同,因此在每個任務完成時,reduce任務就開始複製其輸出。這就是reduece任務的複製階段。reduce任務有少量複製執行緒,因此能夠並行取得map輸出。預設值是5個執行緒,但是這個預設值可以修改設定mapreduce.reduce.shuffle屬性即可。
-
Reduce 會接收到不同 map 任務傳來的資料,並且每個 map 傳來的資料都是有序的。如果 reduce 端接受的資料量相當小,則直接儲存在記憶體中(緩衝區大小由mapred.job.shuffle.input.buffer.percent 屬性控制,表示用作此用途的堆空間的百分比),如果資料量超過了該緩衝區大小的一定比例(由 mapred.job.shuffle.merge.percent 決定),則對資料合併後溢寫到磁碟中。
-
隨著溢寫檔案的增多,後臺執行緒會將它們合併成一個更大的有序的檔案,這樣做是為了給後面的合併節省時間。其實不管在 map 端還是 reduce 端, MapReduce 都是反覆地執行排序,合併操作,現在終於明白了有些人為什麼會說:排序是 hadoop 的靈 魂。
-
合併的過程中會產生許多的中間檔案(寫入磁碟了),但 MapReduce 會讓寫入磁碟的資料儘可能地少,並且最後一次合併的結果並沒有寫入磁碟,而是直接輸入到 reduce函式。合併的時候