MapReduce的輸入輸出格式

默認的mapper是IdentityMapper,默認的reducer是IdentityReducer,它們將輸入的鍵和值原封不動地寫到輸出中。html

默認的partitioner是HashPartitinoer,它根據每條記錄的鍵進行哈希操做來分區。數據庫

 

輸入文件:文件是MapReduce任務的數據的初始存儲地。正常狀況下,輸入文件通常是存在HDFS裏。這些文件的格式能夠是任意的;咱們可使用基於行的日誌文件,也可使用二進制格式,多行輸入記錄或其它一些格式。這些文件會很大—數十G或更大。數組

 

小文件與CombineFileInputFormatapp

        Hadoop在處理大量小文件時的性能稍微遜色一些,一個緣由是FileInputFormat生成的InputSplit老是一個整個或一部分的輸入文件。若是文件比較小,而且數量不少,每次map操做的時候只會處理不多的輸入數據,可是會有不少map任務,每次新的map操做都回形成必定的性能損失。框架

        CombineFileInputFormat能夠緩解這個問題,它對這種狀況作了必定的優化。FileInputFormat將每一個文件分割成1個或多個單元,而CombineFileInputFormat能夠將多個文件打包到一個輸入單元中,這樣每次map操做就會有更多的數據來處理。CombineFileInputFormat會考慮到節點和集羣的位置信息以決定哪些文件應該打包到一個單元中,全部本來的MapReduce的效率就會降低。oop

 

  輸入格式:InputFormat類定義瞭如何分割和讀取輸入文件,它提供有下面的幾個功能:性能

  • 選擇做爲輸入的文件或對象;
  • 定義把文件劃分到任務的InputSplits
  • RecordReader讀取文件提供了一個工廠方法;

  Hadoop自帶了好幾個輸入格式。其中有一個抽象類叫FileInputFormat,全部操做文件的InputFormat類都是從它那裏繼承功能和屬性。當開啓Hadoop做業時,FileInputFormat會獲得一個路徑參數,這個路徑內包含了所須要處理的文件,FileInputFormat會讀取這個文件夾內的全部文件(譯註:默認不包括子文件夾內的),而後它會把這些文件拆分紅一個或多個的InputSplit。你能夠經過JobConf對象的setInputFormat()方法來設定應用到你的做業輸入文件上的輸入格式。下表給出了一些優化

標準的輸入格式:spa

輸入格式日誌

描述

TextInputFormat

默認格式,讀取文件的行

行的字節偏移量

行的內容

KeyValueInputFormat

把行解析爲鍵值對

第一個tab字符前的全部字符

行剩下的內容

SequenceFileInputFormat

Hadoop定義的高性能二進制格式

用戶自定義

用戶自定義

SequenceFileAsTextInputFormat 是SequenceFileInputFormat的變體,它將鍵和值轉換爲Text對象。轉換的時候會調用鍵和值的toString方法。這個格式能夠是順序文件做爲流操做的輸入。    
SequenceFileAsBinaryInputFormat SequenceFileAsBinaryInputFormat是SequenceFileInputFormat的另外一種變體,它將順序文件的鍵和值做爲二進制對象,它們被封裝爲BytesWritable對象,於是應用程序能夠任意地將這些字節數組解釋爲他們想要的類型。    
DBInputForma DBInputForma是一個使用JDBC而且從關係數據庫中讀取數據的一種輸入格式。因爲它沒有任何碎片技術,因此在訪問數據庫的時候必須很是當心,太多的mapper可能會事數據庫受不了。所以DBInputFormat最好在加載小量數據集的時候用。    

4.1MapReduce提供的輸入格式

 

  默認的輸入格式是TextInputFormat,它把輸入文件每一行做爲單獨的一個記錄,但不作解析處理。這對那些沒有被格式化的數據或是基於行的記錄來講是頗有用的,好比日誌文件。更有趣的一個輸入格式是KeyValueInputFormat,這個格式也是把輸入文件每一行做爲單獨的一個記錄。然而不一樣的是TextInputFormat把整個文件行當作值數據,KeyValueInputFormat則是經過搜尋tab字符來把行拆分爲鍵值對。這在把一個MapReduce的做業輸出做爲下一個做業的輸入時顯得特別有用,由於默認輸出格式(下面有更詳細的描述)正是按KeyValueInputFormat格式輸出數據。最後來說講SequenceFileInputFormat,它會讀取特殊的特定於Hadoop的二進制文件,這些文件包含了不少能讓Hadoopmapper快速讀取數據的特性。Sequence文件是塊壓縮的並提供了對幾種數據類型(不只僅是文本類型)直接的序列化與反序列化操做。Squence文件能夠做爲MapReduce任務的輸出數據,而且用它作一個MapReduce做業到另外一個做業的中間數據是很高效的。

 

  輸入塊(InputSplit):一個輸入塊描述了構成MapReduce程序中單個map任務的一個單元。把一個MapReduce程序應用到一個數據集上,便是指一個做業,會由幾個(也可能幾百個)任務組成。Map任務可能會讀取整個文件,但通常是讀取文件的一部分。默認狀況下,FileInputFormat及其子類會以64MB(與HDFS的Block默認大小相同,譯註:Hadoop建議Split大小與此相同)爲基數來拆分文件。你能夠在hadoop-site.xml(譯註:0.20.*之後是在mapred-default.xml裏)文件內設定mapred.min.split.size參數來控制具體劃分大小,或者在具體MapReduce做業的JobConf對象中重寫這個參數。經過以塊形式處理文件,咱們可讓多個map任務並行的操做一個文件。若是文件很是大的話,這個特性能夠經過並行處理大幅的提高性能。更重要的是,由於多個塊(Block)組成的文件可能會分散在集羣內的好幾個節點上(譯註:事實上就是這樣),這樣就能夠把任務調度在不一樣的節點上;所以全部的單個塊都是本地處理的,而不是把數據從一個節點傳輸到另一個節點。固然,日誌文件能夠以明智的塊處理方式進行處理,可是有些文件格式不支持塊處理方式。針對這種狀況,你能夠寫一個自定義的InputFormat,這樣你就能夠控制你文件是如何被拆分(或不拆分)成文件塊的。自定義的文件格式在第五部分有描述。
  輸入格式定義了組成mapping階段的map任務列表,每個任務對應一個輸入塊。接着根據輸入文件塊所在的物理地址,這些任務會被分派到對應的系統節點上,可能會有多個map任務被分派到同一個節點上。任務分派好後,節點開始運行任務,嘗試去最大並行化執行。節點上的最大任務並行數由mapred.tasktracker.map.tasks.maximum參數控制。
  記錄讀取器(RecordReader):InputSplit定義瞭如何切分工做,可是沒有描述如何去訪問它。 RecordReader類則是實際的用來加載數據並把數據轉換爲適合mapper讀取的鍵值對。RecordReader實例是由輸入格式定義的,默認的輸入格式,TextInputFormat,提供了一個LineRecordReader,這個類的會把輸入文件的每一行做爲一個新的值,關聯到每一行的鍵則是該行在文件中的字節偏移量。RecordReader會在輸入塊上被重複的調用直到整個輸入塊被處理完畢,每一次調用RecordReader都會調用Mapper的map()方法。
  Mapper:Mapper執行了MapReduce程序第一階段中有趣的用戶定義的工做。給定一個鍵值對,map()方法會生成一個或多個鍵值對,這些鍵值對會被送到Reducer那裏。對於整個做業輸入部分的每個map任務(輸入塊),每個新的Mapper實例都會在單獨的Java進程中被初始化,mapper之間不能進行通訊。這就使得每個map任務的可靠性不受其它map任務的影響,只由本地機器的可靠性來決定。map()方法除了鍵值對外還會接收額外的兩個參數(譯註:在0.20.×後的版本,接口已變化,由Context對象代替這兩個參數):

  • OutputCollector對象有一個叫collect()的方法,它能夠利用該方法把鍵值對送到做業的reduce階段。
  • Reporter對象提供當前任務的信息,它的getInputSplit()方法會返回一個描述當前輸入塊的對象,而且還容許map任務提供關於系統執行進度的額外信息。setStatus()方法容許你生成一個反饋給用戶的狀態消息,incrCounter()方法容許你遞增共享的高性能計數器,除了默認的計數器外,你還能夠定義更多的你想要的計數器。每個mapper均可以遞增計數器,JobTracker會收集由不一樣處理獲得的遞增數據並把它們彙集在一塊兒以供做業結束後的讀取。

  Partition & Shuffle:當第一個map任務完成後,節點可能還要繼續執行更多的map任務,但這時候也開始把map任務的中間輸出交換到須要它們的reducer那裏去,這個移動map輸出到reducer的過程叫作shuffle。每個reduce節點會分派到中間輸出的鍵集合中的一個不一樣的子集合,這些子集合(被稱爲「partitions」)是reduce任務的輸入數據。每個map任務生成的鍵值對可能會隸屬於任意的partition,有着相同鍵的數值老是在一塊兒被reduce,無論它是來自那個mapper的。所以,全部的map節點必須就把不一樣的中間數據發往何處達成一致。Partitioner類就是用來決定給定鍵值對的去向,默認的分類器(partitioner)會計算鍵的哈希值並基於這個結果來把鍵賦到相應的partition上,自定義的分類器在第五部分有詳細描述。
  排序:每個reduce任務負責歸約(reduceing)關聯到相同鍵上的全部數值,每個節點收到的中間鍵集合在被送到具體的reducer那裏前就已經自動被Hadoop排序過了。
  歸約(Reduce):每一個reduce任務都會建立一個Reducer實例,這是一個用戶自定義代碼的實例,負責執行特定做業的第二個重要的階段。對於每個已賦予到reducer的partition內的鍵來講,reducer的reduce()方法只會調用一次,它會接收一個鍵和關聯到鍵的全部值的一個迭代器,迭代器會以一個未定義的順序返回關聯到同一個鍵的值。reducer也要接收一個OutputCollector和Report對象,它們像在map()方法中那樣被使用。
  輸出格式:提供給OutputCollector的鍵值對會被寫到輸出文件中,寫入的方式由輸出格式控制。OutputFormat的功能跟前面描述的InputFormat類很像,Hadoop提供的OutputFormat的實例會把文件寫在本地磁盤或HDFS上,它們都是繼承自公共的FileInputFormat類。每個reducer會把結果輸出寫在公共文件夾中一個單獨的文件內,這些文件的命名通常是part-nnnnn,nnnnn是關聯到某個reduce任務的partition的id,輸出文件夾經過FileOutputFormat.setOutputPath() 來設置。你能夠經過具體MapReduce做業的JobConf對象的setOutputFormat()方法來設置具體用到的輸出格式。下表給出了已提供的輸出格式:

輸出格式

描述

TextOutputFormat

默認的輸出格式, 以 "key \t value" 的方式輸出行

SequenceFileOutputFormat

輸出二進制文件,適合於讀取爲子MapReduce做業的輸入

NullOutputFormat

忽略收到的數據,即不作輸出 

SequenceFileAsBinaryOutputFormat 與SequenceFileAsBinaryInputFormat相對應,它將鍵/值對看成二進制數據寫入一個順序文件
MapFileOutputFormat MapFileOutputFormat將結果寫入一個MapFile中。MapFile中的鍵必須是排序的,因此在reducer中必須保證輸出的鍵有序。

表4.2: Hadoop提供的輸出格式
  Hadoop提供了一些OutputFormat實例用於寫入文件,基本的(默認的)實例是TextOutputFormat,它會以一行一個鍵值對的方式把數據寫入一個文本文件裏。這樣後面的MapReduce任務就能夠經過KeyValueInputFormat類簡單的從新讀取所需的輸入數據了,並且也適合於人的閱讀。還有一個更適合於在MapReduce做業間使用的中間格式,那就是SequenceFileOutputFormat,它能夠快速的序列化任意的數據類型到文件中,而對應SequenceFileInputFormat則會把文件反序列化爲相同的類型並提交爲下一個Mapper的輸入數據,方式和前一個Reducer的生成方式同樣。NullOutputFormat不會生成輸出文件並丟棄任何經過OutputCollector傳遞給它的鍵值對,若是你在要reduce()方法中顯式的寫你本身的輸出文件而且不想Hadoop框架輸出額外的空輸出文件,那這個類是頗有用的。
  RecordWriter:這個跟InputFormat中經過RecordReader讀取單個記錄的實現很類似,OutputFormat類是RecordWriter對象的工廠方法,用來把單個的記錄寫到文件中,就像是OuputFormat直接寫入的同樣。
  Reducer輸出的文件會留在HDFS上供你的其它應用使用,好比另一個MapReduce做業,或一個給人工檢查的單獨程序。

轉自:http://www.cnblogs.com/spork/

相關文章
相關標籤/搜索