寫在前面:WordCount的功能是統計輸入文件中每個單詞出現的次數。基本解決思路就是將文本內容切分成單詞,將其中相同的單詞聚集在一起,統計其數量作為該單詞的出現次數輸出。
1.MapReduce之wordcount的計算模型
1.1 WordCount的Map過程
假設有兩個輸入文本文件,輸入數據經過默認的LineRecordReader被分割成一行行數據,再經由map()方法得到<key, value>對,Map過程如下:
得到map方法輸出的< key,value>對后,Mapper會將它們按照key值進行排序,並執行Combine過程,將key值相同的value值累加,得到Mapper的最終輸出結果,如圖所示:
1.2 WordCount的Reduce過程
Reducer對從Mapper端接收的數據進行排序,之后由reduce()方法進行處理,將相同主鍵下的所有值相加,得到新的<key, value>對作為最終的輸出結果,如圖所示:
2. 打包運行WordCount程序
通過Eclipse來編譯打包運行自己寫的MapReduce程序(基於Hadoop 2.6.0)。
2.1 下載所需的驅動包
下載地址Group: org.apache.hadoop下載對應版本的驅動包:
- hadoop-common-2.6.0.jar
- hadoop-mapreduce-client-core-2.6.0.jar
- hadoop-test-1.2.1.jar
2.2 創建新的工程
- 使用Eclipse創建名為WordCount的Java Project;
- 在
Project Properties -> Java Build Path -> Libraries -> Add External Jars
添加第一步所下載Jar包, 點擊OK; - 創建WordCount.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 打包源文件
- 在Eclipse -> File ->Export -> Java ->JAR file ->next
- 選中新建的WordCount工程,設置相應的輸出路徑和文件名(這里的輸出路徑一定要記下來,后面會用到),FInish
- 在設置的輸出路徑處生成了WordCount.jar,至此,打包完畢。
2.4 啟動HDFS服務
打開Terminal,進入目錄/usr/local/Cellar/hadoop/2.6.0/sbin
$ start-dfs.sh #啟動HDFS
$ jps #驗證是否啟動成功
1666
2503 SecondaryNameNode
2920 Jps
2317 NameNode
2399 DataNode
成功啟動服務后, 可以直接在瀏覽器中輸入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/&&&&&&&&/Downloads/test* /user/input
#查看上傳到HDFS輸入文件夾中到文件
$ hadoop fs -ls /user/input
#輸出結果
-rw-r--r-- 1 &&&&&& supergroup 666 2015-04-06 10:49 /user/input/test01.html
-rw-r--r-- 1 &&&&&& supergroup 9708 2015-04-06 14:25 /user/input/test02.html
2.6 運行JAR文件
#在當前文件夾創建一個工作目錄 $ mkdir WorkSpace
#下面這句可以不用,只要運行程序時,正確寫入jar所在的完整路徑即可 #將打包好的Jar復制到當前工作目錄下(復制前路徑就是你打包Jar時的存儲路徑) $ cp /Users/&&&&&/Desktop/WorkCount.jar ./WorkSpace #運行Jar文件,各字段含義:hadoop是運行命令命令,jar WorkSpace/WordCount.jar指定Jar文件,WordCount指定Jar文件入口類,/user/input指定job的HDFS上得輸入文件目錄,output指定job的HDFS輸出文件目錄 $ hadoop jar WorkSpace/WordCount.jar WordCount /user/input /user/output
#這里input和output在同一user目錄中,方便管理
顯示如下結果,則說明運行成功:
……省略大量代碼
2.7 查看運行結果
$ hdfs dfs -ls /user/output
Found 2 items -rw-r--r-- 1 xumengting supergroup 0 2015-04-06 15:40 output/_SUCCESS -rw-r--r-- 1 xumengting supergroup 824 2015-04-06 15:40 output/part-r-00000
#查看結果輸出文件中的內容
$ hdfs dfs -cat /user/output/part-r-00000
結果文件一般由2部分組成:
- _SUCCESS文件:表示MapReduce運行成功。
- part-r-00000文件:存放結果,也是默認生成的結果文件
參考文獻:
[1]. 【Hadoop基礎教程】5、Hadoop之單詞計數——http://blog.csdn.net/andie_guo/article/details/44055863
[2]. MapReduce之Wordcount——http://andrewliu.tk/2015/03/29/MapReduce%E4%B9%8BWordCount/#more
[3]. Mac下Hadoop的配置及在Eclipse上編程