1. 程式人生 > >MapReduce的輸出格式

MapReduce的輸出格式

輸出數據 轉存 partition tip 4.2 分區 創建 margin value

1. OutputFormat接口

  OutputFormat為輸出格式接口,主要用於描述輸出數據的格式,它能將輸出的鍵值對寫入特定格式的文件中。輸出格式的層次結構如下

技術分享圖片

2. 文本輸出

  Hadoop默認的輸出格式為文本輸出格式TextOutputFormat,其鍵和值可以使任意類型的,因為該輸出方式會調用toString()方法將它們轉化為字符串。每個鍵/值對由制表符進行分割,當然也可以設定 mapreduce.output.textoutputformat.separator 屬性(舊版本 API 中為 mapred.textoutputformat.separator)改變默認的分隔符。

3. 二進制輸出

  二進制輸出有三種方式:SequenceFileOutputFormat,SequenceFileAsBinaryOutputFormat和MapFileOutputFormat。重點掌握第一種。

  對於SequenceFileOutputFormat,顧名思義,SequenceFileOutputFormat 將它的輸出寫為一個順序文件。如果輸出需要作為後續 MapReduce 任務的輸入,這便是一種好的輸出格式, 因為它的格式緊湊,並且很容易被壓縮。而對於SequenceFileAsBinaryOutputFormat,它將鍵/值對作為二進制格式寫到一個 SequenceFile 容器中。不同的是,MapFileOutputFormat 把 MapFile 作為輸出。MapFile 中的鍵必須順序添加,所以必須確保 reducer 輸出的鍵已經排好序。

4. 多個輸出

  由於默認情況下只有一個 Reducer,輸出只有一個文件。有時可能需要對輸出的文件名進行控制或讓每個 reducer 輸出多個文件。

  當只有一個reduce時,輸出文件命名格式為:part-r-00000。當有兩個reduce時,輸出文件命名格式為:part-r-00000,part-r-00001。當有多個時以此類推。實現Reducer輸出多個文件主要有以下兩種方式:Partitioner和MultipleOutputs。

 4.1 Partitioner

  我們考慮這樣一個需求:按學生的年齡段,將數據輸出到不同的文件路徑下。這裏我們分為三個年齡段:小於等於20歲、大於20歲小於等於50歲和大於50歲。

我們采用的方法是每個年齡段對應一個 reducer。為此,我們需要通過以下兩步實現。

第一步:把作業的 reducer 數設為年齡段數即為3。

  job.setPartitionerClass(PCPartitioner.class);//設置Partitioner類

  job.setNumReduceTasks(3);// reduce個數設置為3

  第二步:寫一個 Partitioner,把同一個年齡段的數據放到同一個分區。

  public static class PCPartitioner extends Partitioner< Text, Text>
     {
                  @Override
                  public int getPartition(Text key, Text value, int numReduceTasks) {

                          // TODO Auto-generated method stub
                          String[] nameAgeScore = value.toString().split("\t");
                          String age = nameAgeScore[1];//學生年齡
                          int ageInt = Integer.parseInt(age);//按年齡段分區

                          // 默認指定分區 0

                          if (numReduceTasks == 0)

                                   return 0;
                          //年齡小於等於20,指定分區0

                          if (ageInt <= 20) {

                                   return 0;
                          }
                          // 年齡大於20,小於等於50,指定分區1

                          if (ageInt > 20 && ageInt <= 50) {

                                   return 1 % numReduceTasks;
                          }
                          // 剩余年齡,指定分區2
                          else

                                   return 2 % numReduceTasks;
                  }
    }

  這種方法即實現了多文件輸出,但也只能滿足此種需求。很多情況下是無法實現的,因為這樣做存在兩個缺點:

  1)需要在作業運行之前需要知道分區數和年齡段的個數,如果分區數很大或者未知,就無法操作。

2)一般來說,讓應用程序來嚴格限定分區數並不好,因為這樣可能導致分區數少或分區不均。

 4.2 MultipleOutputs

  MultipleOutputs 類可以將數據寫到多個文件,這些文件的名稱源於輸出的鍵和值或者任意字符串。這允許每個 reducer(或者只有 map 作業的 mapper)創建多個文件。 采用name-m-nnnnn 形式的文件名用於 map 輸出,name-r-nnnnn 形式的文件名用於 reduce 輸出,其中 name 是由程序設定的任意名字, nnnnn 是一個指明塊號的整數(從 00000 開始)。塊號保證從不同塊(mapper 或 reducer)寫的輸出在相同名字情況下不會沖突。

  實例將在下一篇博文給出!

5. 數據庫輸出 

  DBOutputFormat 適用於將作業輸出數據(中等規模的數據)轉存到Mysql、Oracle等數據庫。如果數據量較大請考慮其他方法將輸出數據導入或轉存到數據庫中。

以上就是博主為大家介紹的這一板塊的主要內容,這都是博主自己的學習過程,希望能給大家帶來一定的指導作用,有用的還望大家點個支持,如果對你沒用也望包涵,有錯誤煩請指出。如有期待可關註博主以第一時間獲取更新哦,謝謝!

版權聲明:本文為博主原創文章,未經博主允許不得轉載。

MapReduce的輸出格式