Hadoop學習筆記-MapReduce工作原理

本文從一個初學者的角度出發,用通俗易懂的語言介紹Hadoop中MapReduce的工作原理。在介紹MapReduce工作原理前,本文先介紹HDFS的工作原理及架構,再介紹MapReduce的工作原理以及Shuffle的過程。

HDFS

HDFS是Hadoop的分佈式文件系統,HDFS中的文件會默認存儲3份,存儲在不同的機器上,提供容錯機制,副本丟失或者宕機的自動恢復。HDFS的架構如下圖所示,總體上採用Master/Slave的架構。整個HDFS架構由Client、NameNode、Secondary NameNode和DataNode構成,NameNode負責存儲整個集羣的元數據信息,Client可以根據元數據信息找到對應的文件。DataNode負責數據的實際存儲,當一個文件上傳到HDFS的時候,DataNode會按照Block爲基本單位分佈在各個DataNode中,而且爲了保護數據的一致性和容錯性,一般一份數據會在不同的DataNode上默認存儲三份。如下架構圖所示,當Client端上傳了一個文件,這個文件被分成了4個block存在4個不同的DataNode裏頭,每個block會默認的存儲三份,分別存在不同的DataNode裏。而NameNode中的Block Map則維護着每個block和DataNode的配置關係,這樣,整個文件在DataNode中的存儲結構就在NameNode中記錄下來。SecondaryNameNode不是NameNode的熱備份,主要是爲了承擔一部分NameNode中比較消耗內存的工作而設置。

HDFS框架

MapReduce

MapReduce的工作過程分成兩個階段,map階段和reduce階段。每個階段都有鍵值對作爲輸入輸出,map函數和reduce函數的具體實現由程序員完成。MapReduce的框架和HDFS分佈式文件系統是運行在一組相同的節點上,也就是說計算節點和存儲節點通常在一起,這種配置就允許框架在那些已經存好數據的節點上高效的調度任務,所以一般情況下,map運行的節點通常與其所要處理的那個block數據的存儲節點是同一個。MapReduce的框架也是採用Master/Slave的方式組織,如下圖所示,也是由四部分組成,分別爲Client、JobTracker、TaskTracker以及Task。JobTracker主要負責資源監控和作業調度。JobTracker監控TaskTracker是否存活,任務執行的狀態以及資源的使用情況,並且把得到的信息交給TaskSceduler。TaskSceduler根據每個TaskTracker的情況給分配響應的任務,在Hadoop系統中,TaskSceduler是一個可插拔的模塊,Hadoop的使用者可以根據自己的需求定製TaskSceduler,實現自己的目標。

mapreduce框架

TaskTracker會週期性的通過heartbeats向JobTracker發送資源的使用情況,任務的執行狀況等信息,同時會接收JobTracker的指令,TaskTracker把自己可支配的資源分成若干個Slot,Task只有拿到一個Slot資源才能執行任務。
Task任務分成Map Task和Reduce Task兩種任務,都是由TaskTracker進行調度的。Map 任務的數據來源於HDFS,而數據在HDFS中的存儲方式是block,而在Map 任務中,處理的數據單元是Split,一般情況下,Split是一個邏輯概念,包括數據的起始位置,數據長度等信息,Split和block數據的對應關係可以由用戶定義,Split的多少決定了Map Task的多少,一個Split只由一個Map Task進行處理。Map Task先把需要處理的Split轉化成key/value對,然後調用用戶自定義的map()函數,生成map的臨時結果,分成partition存在本地磁盤中,Reduce Task會對每個partition的數據進行Reduce操作,Reduce的輸出結果會輸出到HDFS上。
MapReduce的技術核心在於Shuffle,Shuffle這個過程存在的最基本的目的在於減少在跨節點拉取數據的過程中的帶寬開銷以及IO的損耗,因爲Map Task最終處理的結果會產生很多中間的臨時文件,而且Map Task和Reduce Task很有可能不在同一個節點上執行,很多情況下Reduce Task執行的時候需要跨節點的拉取數據,所以必須使拉取的數據量儘量小,以免整個集羣的資源大量消耗在IO中。Shuffle的過程橫跨Map Task和Reduce Task。Shuffle在Map端的過程如下圖所示。Map Task讀取Split的數據之後,經過用戶的Map()函數之後輸出的是一個一個的鍵值對,假設這個MapReduce任務中有8個MapTask,3個Reduce Task,Map Task的輸出最終由哪個Reduce來處理,可以通過Partition來實現。在MapReduce默認的實現中,Partition只是對Key進行哈希操作然後取模,默認取模的方式是爲了平衡每個Reduce之間的任務量,如果用戶對Partition有特殊的需求,也可以定製並設置到Job上。Partition的輸出結果會被寫入臨時內存緩衝區,內存緩衝區的大小是有限制的,一般情況下默認爲100MB,在達到緩衝區的臨界值的情況下,需要將緩衝區的數據寫入磁盤,才能再重新啓用這個緩衝區。從內存往磁盤寫數據的過程稱爲Spill(溢寫)。在溢寫操作啓動後,需要溢寫的這部分內存被鎖定,被鎖定的內存數據將會被記錄到磁盤中去,而溢寫的過程不會影響Map()的輸出結果往緩衝區輸入。在溢寫操作過程中,數據寫入磁盤前,會對數據進行一個二次快速排序,首先是對數據所屬的Partition排序,然後對每個Partition中再按照Key排序。Sort的輸出包括一個索引文件和數據文件。如果用戶定義了Combiner,則會對Sort後的數據進行一個簡單的Reduce,使得Map端得到的數據更加緊湊。每當內存數據達到Spill的臨界值的時候,都會進行Spill操作,從而會產生多個Spill文件,在Map任務完成之前,所有的Spill文件都會被歸併排序爲一個索引文件和數據文件。
Map端Spill流程

當Spill歸併完畢之後,Map端刪除所有的臨時文件並且告知TaskTracker其Map任務已經完成,Reduce端可以開展工作,工作流程如下圖所示。Reduce端一開始的主要工作是把Map端的輸出結果拷貝,同樣,Map端的輸出結果通常會先輸出到緩衝區中,如果緩衝區不足,會溢寫到磁盤中,溢寫到磁盤過程中,merge的操作一直在進行,如果Map端的輸出結果計較小,沒有填滿緩衝區,這數據會直接從緩衝區直接進入Reduce操作,Reduce操作完成後,輸出結果會直接放到HDFS上。
Reduce端Spill流程

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