1)InputFormat的類圖:
InputFormat 直接子類有三個:DBInputFormat、DelegatingInputFormat和FileInputFormat,分別表示輸入文件的來源為從數據庫、用於多個輸入以及基於文件的輸入。對於FileInputFormat,即從文件輸入的輸入方式,又有五個繼承子類:CombineFileInputFormat,KeyValueTextInput,NLineInoutFormat,SequenceFileInputFormat,TextInputFormat。
2)InputSplit的類圖
輸入分片InputSplit 類有三個子類繼承:FileSplit (文件輸入分片),CombineFileSplit(多文件輸入分片)以及DBInputSplit(數據塊輸入分片)。
3)InputFormat:
InputFormat有三個作用:
a.驗證作業數據的輸入形式和格式(要與MR程序中使用的格式相同,比如是TextInputFormat還是DBInputFormat)
b.將輸入的數據切分為多個邏輯上的InputSplit,其中每一個InputSplit作為一個MApper的輸入。
c.提供一個RecordReader,用於將InputSplit的內容轉換為可以作為map輸入的<k,v>鍵值對。
使用代碼來指定MR作業數據的輸入格式:
job.setInputFormatClass(TextInputFormat.class)
其實,InputFormat是一個抽象類,只是提供了兩個抽象方法:
abstract List<InputSplit>getSplits(JobContext context);
abstract RecordReader<K,V> createRecordReader(InputSplit split,TaskAttemptContext context)
只提供兩個抽象方法是有原因的,首先不同的格式的文件切片的方法不同(對應於getSplits),同一份文件可能希望讀出不同形式的內容(對應createRecordReader)。
getSplits:
InputFormat的直接派生類需要實現此方法,例如FileInputFormat和DBInputFormat。另外,InputSplit的類型在選擇了InputFormat的類型就已經確定了的,因為每個InputFormat的派生類都實現了getSplits,在此方法內部已經生成了對應的InputSplit。
createRecordReader:
FileInputFormat的派生類都實現了這個方法。
4)
InputSplit:
任何數據分塊兒的實現都繼承自抽象基類InputSplit,它位於org.apache.hadoop.mapreduce.InputSplit。此抽象類中有兩個抽象方法:
abstract long getLength() abstract String[] getLocation()
getLength()返回該塊兒的大小,單位是字節。getLocation()返回存儲該數據塊的數據節點的名稱,例如:String[0]="Slave1",String[1]="Slave2".
這兩個方法也是需要在InputSplit的派生類中實現的。
5)
InputSplit的大小:
一個數據分片的大小由以下三行代碼確定:
goalSize=totalSize/(numSplits==0?1:numSplits) //totalSize是輸入數據文件的大小,numSplits是用戶設置的map數量,就是按照用戶自己 //的意願,每個分片的大小應該是goalSize minSize=Math.max(job.getLong("mapred.min.split.size",1),minSplitSize) //hadoop1.2.1中mapred-default.xml文件中mapred.min.split.size=0,所以job.getLong("mapred.min.split.size",1)=0,而minSplitSize是InputSplit中的一個數據成員,在File//Split中值為1.所以minSize=1,其目的就是得到配置中的最小值。 splitSize=Math.max(minSize,Math.min(goalSize,blockSize)) //真正的分片大小就是取按照用戶設置的map數量計算出的goalSize和塊大小blockSize中最小值(這是為了是分片不會大於一個塊大小,有利於本地化計算),並且又比minSize大的值。