在hadoop中。每一個mapreduce任務都會被初始化為一個Job。
每一個Job又能夠分為兩個階段:map階段和reduce階段。這兩個階段分別用兩個函數來表示,即map函數和reduce函數。map函數接收一個<key,value>形式的輸入,然后產生相同為<key,value>形式的中間輸出,hadoop會負責將全部具有相同中間key值的value集合到一起傳遞給reduce函數,reduce函數接收一個如<key,(list of values)>形式的輸入,然后對這個value集合進行處理並輸出結果,reduce的輸出 也是<key,value>形式的。
為了方便理解,分別將三個<key,value>對標記為<k1,v1>、<k2,v2>、<k3,v3>。那么上面所述的過程就能夠用下圖來表示了。
1、InputFormat()和InputSplit
InputSplit是hadoop中用來把輸入數據傳送給每一個單獨map。InputSplit存儲的並不是數據本身,而是一個分片長度和一個記錄數據位置的數組。生成InputSplit的方法能夠通過InputFormat()來設置。
當數據傳送給map時,map會將輸入分片傳送到InputFormat()上,InputFormat()則調用getRecordReader()方法生成RecordReader。RecordReader再通過createKey()、createValue()方法創建可供map處理的<key,value>對,即<k1,v2>。簡而言之,InputFormat()方法是用來生成可供map處理的<key,value>對的。
TextInputFormat是hadoop默認的輸入方法,在TextInputFormat中,每一個文件(或當中一部分)都會單獨作為map的輸入,二這是繼承自FileInputFoemat的。之后。每行數據都會生成一條記錄。每條記錄則表示成<key,value>形式:
key值是每一個數據的記錄在數據分片中的字節偏移量,數據類型是LongWritable;
value值是每行的內容,數據類型是Text。
2、OutputFormat()
對於每一種輸入格式都有一種輸出格式與其相應。
相同,默認的輸出格式是TextOutputFormat。這樣的輸出方式與輸入類似,會將每條記錄以一行的形式存入文本文件。
只是,他的鍵和值能夠是隨意形式的。由於程序內部會調用toString方法將鍵和值轉化為string類型再輸出。
3、map()
map()函數繼承自MapReduceBase,而且它實現了Mapper接口,此接口是一個范型類型,它有4種形式的參數,分別用來指定Map()的輸入key值類型、輸入value值類型、輸出key值類型和輸出value值類型。
4、reduce()
與map()類似,reduce函數也繼承自MapReduceBase,須要實現Reducer接口,Reduce函數以Map()的輸出作為輸入。
負責控制及調度MapReduce的Job的是JobTracker。負責運行MapReduce的Job的是TaskTracker。
當然,MapReduce在運行時是分成Map Task和Reduce Task來處理的,而不是完整的Job。
簡單的控制流大概是這種:JobTracker調度任務給TaskTracker,TaskTracker運行任務時,會返回進度報告。
JobTracker則會記錄進度的進行狀況。假設某個TaskTracker上的任務運行失敗。那么JobTracker會把這個任務分配給還有一台TaskTracker,直到任務運行完畢。
這里更具體的解釋一下數據流。數據首先依照TextInputFormat形式被處理成多個InputSplit,然后輸入到多個Map中,Map程序會讀取InputSplit指定位置的數據,然后依照設定的方式處理該數據,最后寫入到本地磁盤中,注意。這里並非寫到HDFS上,這應該非常好理解,由於Map的輸出在Job完畢后殼刪除了。因此不須要存儲到HDFS上,盡管存儲到HDFS上會更安全,可是由於網絡傳輸會減少MapReduce任務的運行效率,因此Map的輸出文件時寫在本地磁盤上的。
假設Map程序在沒來得及將數據傳送給Reduce時就崩潰了(程序出錯或者機器崩潰),那么JobTracker僅僅須要另選一台機器又一次運行這個Task就能夠了。
Reduce會讀取Map的輸出數據。合並value。然后將他們輸出到HDFS上。
Reduce的輸出會占用非常多的網絡寬帶,只是這與上傳數據一樣是不可避免的。
此外,還有兩中情況須要注意:
1、MapReduce在運行過程中往往不止一個Reduce Task。Reduce Task的數量是能夠程序指定的。
當存在多個Reduce Task時,每一個Reduce會搜集一個或多個key值。須要注意的是當出現多個Reduce Task時,每一個Reduce Task都會生成一個輸出文件。
2、另外,沒有Reduce任務的時候,系統會直接將Map的輸出結果作為終於結果,同一時候Map Task的數量能夠看做是Reduce Task的數量,即有多少個Map Task 就有多少個輸出文件。