MapReduce的大體流程是這樣的,:
由圖片可以看到mapreduce執行下來主要包含這樣幾個步驟
1.首先對輸入資料來源進行切片
2.master調度worker執行map任務
3.worker讀取輸入源片段
4.worker執行map任務,將任務輸出儲存在本地
5.master調度worker執行reduce任務,reduce worker讀取map任務的輸出檔案
6.執行reduce任務,將任務輸出儲存到HDFS
若對流程細節進行深究,可以得到這樣一張流程圖
角色描述:
JobClient:執行任務的用戶端
JobTracker:任務調度器
TaskTracker:任務跟蹤器
Task:具體的任務(Map OR Reduce)
從生命週期的角度來看,mapreduce流程大概經曆這樣幾個階段:初始化、分配、執行、反饋、成功與失敗的後續處理
每個階段所做的事情大致如下
任務初始化
1.JobClient對資料來源進行切片
切片資訊由InputSplit對象封裝,介面定義如下:
public interface InputSplit extends Writable { long getLength() throws IOException; String[] getLocations() throws IOException;}
可以看到split並不包含具體的資料資訊,而只是包含資料的引用,map任務會根據引用地址去載入資料
InputSplit是由InputFormat來負責建立的
public interface InputFormat<K, V> { InputSplit[] getSplits(JobConf job, int numSplits) throws IOException; RecordReader<K, V> getRecordReader(InputSplit split,JobConf job,Reporter reporter) throws IOException;}
JobClient通過getSplits方法來計算切片資訊,切片預設大小和HDFS的塊大小相同(64M),這樣有利於map任務的本地化執行,無需通過網路傳遞資料
切片成功後,JobClient會將切片資訊傳送至JobTracker
2.通過jobTracker產生jobId
JobTracker.getNewJobId()
3.檢查輸出目錄和輸入資料來源是否存在
輸出目錄已存在,系統拋出異常
輸入來源目錄不存在,系統拋出異常
4.拷貝任務資源到jobTracker機器上(封裝任務的jar包、叢集設定檔、輸入源切片資訊)
任務分配
JobTracker遍曆每一個InputSplit,根據其記錄的引用地址選擇距離最近的TaskTracker去執行,理想情況下切片資訊就在TaskTracker的本地,這樣節省了網路資料轉送的時間
JobTracker和TaskTracker之間是有心跳通訊的邏輯的,通過彼此間不停的通訊,JobTracker可以判斷出哪些TaskTracker正在執行任務,哪些TaskTracker處於空閑狀態,以此來合理分配任務
任務執行
TaskTracker接到任務後開始執行如下操作:
1.將任務jar包從HDFS拷貝到本地並進行解壓
2.建立一個新的JVM來執行具體的任務,這樣做的好處是即使所執行的任務出現了異常,也不會影響TaskTracker的運行使用
如果所執行的任務是map任務,則處理流程大致如下:
首先載入InputSplit記錄的資料來源切片,通過InputFormat的getRecordReader()方法
擷取到Reader後,執行如下操作:
K key = reader.createKey();V value = reader.createValue();while (reader.next(key, value)) {//遍曆split中的每一條記錄,執行map功能函數 mapper.map(key, value, output, reporter);}執行反饋
mapreduce的執行是一個漫長的過程,執行期間會將任務的進度反饋給使用者
任務結束後,控制台會列印Counter資訊,方便使用者以全域的視角來審查任務
執行成功
清理MapReduce本機存放區(mapred.local.dir屬性指定的目錄)
清理map任務的輸出檔案
執行失敗
1.如果task出現問題(map或者reduce)
錯誤可能原因:使用者代碼出現異常;任務超過mapred.task.timeout指定的時間依然沒有返回
錯誤處理:
首先將錯誤資訊寫入日誌
然後jobtracker會調度其他tasktracker來重新執行次任務,如果失敗次數超過4次(通過mapred.map.max.attempts和mapred.reduce.max.attempts屬性來設定,預設為4),則job以失敗告終
如果系統不想以這種方式結束退出,而是想通過Task成功數的百分比來決定job是否通過,則可以指定如下兩個屬性
mapred.max.map.failures.percent map任務最大失敗率
mapred.max.reduce.failures.percent reduce任務最大失敗率
如果失敗比率超過指定的值,則job以失敗告終
2.如果是tasktracker出現問題
判斷問題的依據:和jobtracker不再心跳通訊
jobtracker將該tasktracker從資源集區中移除,以後不在調度它
3.jobtracker出現問題
jobtracker作為系統的單點如果出現問題也是最為嚴重的問題,系統將處於癱瘓