hadoop學習筆記----map-reduce工作原理

MapReduce的作業(job)是由客戶端提交給Hadoop集羣的。一個job包括了輸入數據,MapReduce程序和配置信息。Hadoop將作業非爲若干個任務(task)來執行,其中包括map任務和reduce任務。

 

 

 

有兩類節點和task的執行相關,一類是jobtracker,另外一類是tasktracker。

 

jobtracker通過調度tasktracker上運行的任務來協調所有運行在系統上的作業。

 

tasktracker在運行任務的同時將運行的進度返回給jobtracker,jobtracker由此記錄每項作業的情況,如果有tasktracker執行任務失敗,則jobtracker可以在另外一個tasktracker上重新調度失敗的任務。

 

 

Hadoop將MapReduce的輸入數據劃分成等長的數據塊,被稱爲輸入分片。hadoop爲每個分片構建一個map任務,並該任務運行由用戶定義的map函數對分片中的每條記錄。

 

對於大部分作業來說,一個合理的分片大小趨向於HDFS的一個塊大小。

Hadoop在存儲有輸入數據的節點上運行map任務,可以獲得最佳性能(數據本地化優化)。

這就是最佳分片大小與HDFS塊大小相同的原因:因爲他是確保可以存儲在單個結點上的最大輸入塊大小。如果分片誇兩個數據庫,那麼對任何一個HDFS節點,基本上都不可能同時存儲這兩個數據庫,因此分片中的部分數據需要通過網絡傳輸到Map任務節點。與使用本地數據運行整個map相比,就顯得笨拙了。

 

map-reduce的運行流程:

 

1.map-reduce 程序啓動作業

2.jobclient向jobTracker請求一個新的jobId。同事檢查作業輸入和輸出說明。如果不合法就返回異常

3.jobclient 將運行作業所需要的資源複製到一個以作業ID命名的目錄下jobtracker的文件系統中。作業jar的副本較多,因此在運行作業的任務時,集羣中有很多副本可供taskTracker訪問。

4.jobclient告知jobTracker作業準備執行

5.jboTracker接收到對其submitJob()方法的調用後,會把此調用放入一個內部隊列中,交由作業調度進行調度,並對其初始化。

6.爲了創建任務運行列表,作業調度器首先從共享文件系統中獲取jobClient以計算好的輸入分片信息,然後爲每一個分片創建map任務。創建reduce任務數量由jobConf的mapred.reduce.task屬性決定.然後調度器創建相應數量的要運行的reduce任務。任務在此時被指定ID

7.tasktracker運行一個簡單的循環來定期發送“心跳”給jobtracker,用來告訴jobtracker它自己是否還存活和是否準備好運行新的任務。如果是,jobtracker會爲他分配一個任務,並使用“心跳”返回值與tasktracker進行通信。

  在爲tasktracker選擇任務(task)之前,jobtracker首先要選定任務所在的作業(job)。選擇好作業之後jobtracker就可以作爲該作業選定一個任務。對於map任務和reduce任務,tasktacker有固定數量的任務槽。eg:一個tasktracker可能同時運行兩個map任務和reduce任務。默認調度器在處理reduce任務之前會填滿空閒的map任務草。因此,如果tasktracker至少有一個空閒的map任務槽,jobtracker會爲它選擇一個map任務,否則選擇一個reduce任務。

  在選擇reduce任務的時候,jobtracker簡單的從待運行的reduce任務列表中選取下一個來執行,用不着考慮數據的本地化。對於一個map任務jobtracker會考慮tasktracker的網絡位置,並選取一個距離與其輸入分片最近的tasktracker。最理想的情況是 數據本地化的(任務運行在和輸入分片在同一個機器上)。次之是 機架本地化的。

 

tasktracker執行任務:通過共享文件系統把作業的jar文件複製到tasktracker所在的文件系統,從而實現作業的jar文件本地化,同時,tasktracker將應用程序所需要的全部文件從分佈式緩存複製到本地磁盤。然後tasktracker爲任務新建一個本地工作目錄,並把jar文件中的內容解壓到這個文件夾下,然後tasktracker新建一個TaskRunner實例來運行該任務。TaskRunner啓動一個新的JVM來運行每個任務,以便用戶自定義的map和reduce函數的人和問題不會影響到tasktracker。子進程通過接口與父進程通信。任務的資進程每隔幾秒便告知父進程它的進度,直到任務完成。

 

當jobtracker收到作業的最後一個任務已完成的通知後,便把作業狀態設置爲“成功”。然後在jobclient查詢狀態時直到任務已經完成。於是jobclient打印一條消息告知用戶,然後從runJob方法返回。

最後jobtracker清空作業的工作狀態,指示tasktracker也清空作業的工作狀態(eg:刪除中間輸出)。

 

 

 

 

map任務將結果寫入本地硬盤,而非HDFS。因爲map任務的結果是中間結果,要給reduce任務進行再次處理,處理完之後map任務的結果就沒有價值了,通常是被刪掉。HDFS上的同一份數據,通常情況下是要備份的。如果存入HDFS,那麼就有些小題大做了。

 

 MapReduce確保每個reducer的輸入都按鍵排序。系統執行排序的過程---將map輸出作爲輸入傳給reducer,稱爲爲shuffle。

 

 

map產生結果之後會先在內存中,過了一定的量之後開始寫入本地硬盤。

 

寫入磁盤之前,線程先根據數據最終要送到的reducer把數據劃分成相應的分區(partition)。在每個分區中,後臺線程按鍵進行行內排序,如果有一個combiner,它會在排序後的輸入上運行。

一旦緩衝區達到閾值,就開始新建溢出文件。所以在map任務寫完其最後一個輸出記錄之後,會有幾個溢出寫文件。在溢出寫文件被合併成一個已經分區且排序出的輸出文件。

 

combiner的意義在於讓寫入本地磁盤和傳到reducer上的數據更加緊湊。

 

reducer通過http方式得到輸出文件的分區。map輸入文件位於運行map任務的tasktracker的本地磁盤上。現在,tasktracker需要爲分區文件運行reduce任務。這個reduce任務通常需要集羣上若干個map任務的輸出作爲其特殊的分區文件。每個map任務完成時間可能不同。因此只要有一個任務完成,reduce任務就開始複製其輸出。如果map輸出相當小,則會被複制到 reduce tasktracker的內存中,否則會被複制到磁盤。一旦內存緩衝區達到閥值大小或者達到map輸出閥值,則合併後溢出寫到磁盤中。隨着磁盤上的副本增多,後臺線程會將他們合併爲更大,排好序的文件。爲後邊的合併節省一些時間。複製完所有map輸出被複制期間,reduce任務進入合併階段。這階段將合併map輸出,維持其順序排序。

 

在reduce階段,對已排序輸出中的每個鍵都調用reduce函數。此階段的輸出直接寫到HDFS中。

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