MapReduce之WordCount

本文章采用創作共用版權協議, 要求署名、非商業用途和保持一致. 轉載本文章必須也遵循署名-非商業用途-保持一致的創作共用協議.

1. 再述MapReduce計算模型


  • JobTracker用于管理和調度工作(一個集群只有一個JobTracker)
  • TaskTracker用于執行工作
  • 每個MapReduce任務被初始化為一個Job, 每個Job分為Map(接收鍵值對)和Reduce階段

InputSplit(存儲分片長度和記錄數據位置的數組)把輸入數據傳送給單獨的Map, 數據傳給Map后, Map將輸入分片傳送到InputFormat()上, InputFormat()(用來生成可供Map處理的鍵值對)調用getRecordReader()方法生成RecordReader, RecordReader再通過createKey(), createValue()方法創建可供Map處理的鍵值對.TextInputFormat是Hadoop默認的輸入方法, 每個文件都讀作為Map的輸入, 每行數組生成一條鍵值對(key在數據分片中的字節偏移量LongWritable, value是每行內容Text)

2. 編譯打包運行WordCount


總結一下通過Eclipse來編譯打包運行自己寫的MapReduce程序(基于Hadoop2.6.0)

2.1. Hadoop庫

在編寫Hadoop程序會用到Hadoop庫, 所以需要一些Hadoop庫文件, 用于編譯

  • hadoop-common-2.6.0.jar
  • hadoop-mapreduce-client-core-2.6.0.jar
  • hadoop-test-1.2.1.jar

下載地址Group: org.apache.hadoop下載對應版本的庫文件

2.2. 創建工程

  1. 使用Eclipse創建名為WordCount的工程
  2. Project Properties -> Java Build Path -> Libraries -> Add External Jars 添加第一步所下載Jar包, 點擊OK
  3. 創建WordCount.java源文件
#WorkCount.java

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    /*
     * LongWritable 為輸入的key的類型
     * Text 為輸入value的類型
     * Text-IntWritable 為輸出key-value鍵值對的類型
     */
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());  // 將TextInputFormat生成的鍵值對轉換成字符串類型
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
      }
    }
  }

  public static class IntSumReducer
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();
    /*
     * Text-IntWritable 來自map的輸入key-value鍵值對的類型
     * Text-IntWritable 輸出key-value 單詞-詞頻鍵值對
     */
    public void reduce(Text key, Iterable<IntWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();  // job的配置
    Job job = Job.getInstance(conf, "word count");  // 初始化Job
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);  
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));  // 設置輸入路徑
    FileOutputFormat.setOutputPath(job, new Path(args[1]));  // 設置輸出路徑
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

2.3. 打包源文件

  1. File -> Export -> Java -> JAR File, 然后點擊next
  2. 選中WordCount源文件, 設置輸出路徑和文件名WordCount.jar, 選擇Finish則打包成功
  3. 在輸出路徑生成Wordcount.jar

2.4. 啟動HDFS服務

打開目錄/usr/local/Cellar/hadoop/2.6.0/sbin

$ start-dfs.sh  #啟動HDFS
$ jps  #驗證是否啟動成功
8324 Jps
8069 DataNode
7078 NodeManager
6696 NameNode
6987 ResourceManager
3453 SecondaryNameNode
$ stop-dfs.sh  #停止HDFS

成功啟動服務后, 可以直接在瀏覽器中輸入http://localhost:50070/訪問Hadoop頁面

2.5. 將輸入文件上傳到HDFS

打開目錄/usr/local/Cellar/hadoop/2.6.0/bin

#在HDFS上創建輸入/輸出文件夾
$ hdfs dfs -mkdir /user
$ hdfs dfs -mkdir /user/input
$ hdfs dfs -ls /user
#上傳本地file中文件到集群的input目錄下
$ hdfs dfs -put /Users/andrew_liu/Java/Hadoop/input/* /user/input
#查看上傳到HDFS輸入文件夾中到文件
$ hadoop fs -ls /user/input

#輸出結果
-rw-r--r--   1 andrew_liu supergroup    1808033 2015-04-05 12:37 /user/input/rural.txt
-rw-r--r--   1 andrew_liu supergroup    2246756 2015-04-05 12:37 /user/input/science.txt

2.6. 運行Jar文件

#在當前文件夾創建一個工作目錄
$ mkdir WorkSpace 
#將打包號的Jar包復制到當前工作目錄
$cp /usr/local/Cellar/hadoop/2.6.0/bin/WorkSpace/WordCount.jar ./WorkSpace
#運行Jar文件, 各字段的意義(Hadoop打包命令, 指定Jar文件, 指定Jar文件入口類, 指定job的HDFS上的輸入文件目錄, 指定job的HDFS輸出文件目錄)
$ hadoop jar WorkSpace/WordCount.jar WordCount /user/input output
... 省略部分
    File System Counters
        FILE: Number of bytes read=2025025
        FILE: Number of bytes written=4443318
        FILE: Number of read operations=0
        FILE: Number of large read operations=0
        FILE: Number of write operations=0
        HDFS: Number of bytes read=10356334
        HDFS: Number of bytes written=616286
        HDFS: Number of read operations=25
        HDFS: Number of large read operations=0
        HDFS: Number of write operations=5
    Map-Reduce Framework
        Map input records=33907
        Map output records=663964
        Map output bytes=6687108
        Map output materialized bytes=1005779
        Input split bytes=216
        Combine input records=663964
        Combine output records=68147
        Reduce input groups=55800
        Reduce shuffle bytes=1005779
        Reduce input records=68147
        Reduce output records=55800
        Spilled Records=136294
        Shuffled Maps =2
        Failed Shuffles=0
        Merged Map outputs=2
        GC time elapsed (ms)=187
        Total committed heap usage (bytes)=1323827200
    Shuffle Errors
        BAD_ID=0
        CONNECTION=0
        IO_ERROR=0
        WRONG_LENGTH=0
        WRONG_MAP=0
        WRONG_REDUCE=0
    File Input Format Counters
        Bytes Read=4054789
    File Output Format Counters
        Bytes Written=616286

2.7. 查看運行結果

#查看FS上output目錄內容
$ hdfs dfs -ls output
-rw-r--r--   1 andrew_liu supergroup          0 2015-04-05 13:20 output/_SUCCESS
-rw-r--r--   1 andrew_liu supergroup     616286 2015-04-05 13:20 output/part-r-00000 # 存放結果文件
#查看結果輸出文件內容
hdfs dfs -cat output/part-r-00000

2.8. MapReduce運行流程

  • JobTracker調度任務個TaskTracker, TaskTracker執行任務時, 返回進度報告, 如果執行失敗, JobTracker將任務分配給另一個TaskTracker, 知道任務完成
  • 數據按照TextInputFormat被處理成InputSplit, 輸入到Map中, Map讀取InputSplit指定位置的數據, 按照設定的方式處理數據, 最后寫入本地磁盤
  • Reduce讀取Map輸出數據, 合并value, 然后輸出到HDFS上

3. MapReduce任務優化


  • 計算性能優化
  • I/O操作優化
  1. 任務調度(就近原則, 選用空閑原則)
  2. 數據預處理應合理設置block快大小及Map和Reduce任務數量
  3. combine函數用于本地合并數據的函數, 運行用戶combine用于本地合并, 可減少網絡I/O的消耗
  4. 對Map輸出和最終結果壓縮
  5. 自定義comparator實現數據的二進制比較, 省去數據序列化和反序列化時間

4. Hadoop流


當一個可執行未見作為Mapper時, 每個Map任務以一個獨立的進程啟動可執行未見, 任務執行時, 會把輸入劃分成行提供給可執行文件, 并作為Map的標準輸入, Map從標準輸出中收集數據, 并轉換為<key, value>輸出

Reduce任務啟動可執行文件, 將鍵值對轉化為標準輸入, Reduce從標準輸出中收集數據, 并轉換為<key, value>輸出

5. 參考鏈接


更多精彩請查看個人博客-雪憶

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容

  • 目的這篇教程從用戶的角度出發,全面地介紹了Hadoop Map/Reduce框架的各個方面。先決條件請先確認Had...
    SeanC52111閱讀 1,748評論 0 1
  • MapReduce框架結構## MapReduce是一個用于大規模數據處理的分布式計算模型MapReduce模型主...
    Bloo_m閱讀 3,781評論 0 4
  • MapReduce是一個數據處理的編程模型。這個模型很簡單,但也不是簡單到不能夠支持一些有用的語言。Hadoop能...
    單行線的旋律閱讀 1,534評論 0 2
  • MapReduce是面向大數據并行處理的計算模型、框架和平臺。MapReduce是一個基于集群的高性能并行計算平臺...
    VVictoriaLee閱讀 433評論 0 1
  • 謹以此文獻給天下的母親 我電腦的桌面是母親的照片。 那是幾年前,母親來姐姐家,我給拍下的。照片里的母親,美麗著,隱...
    淡淡春山閱讀 472評論 9 19