本文源碼碼雲地址:https://gitee.com/MaxBill/hadoophtml
在上篇《hadoop(02)、使用JAVA API對HDFS進行基本操做》中,經過JAVA API鏈接HDFS系統進行了基本的操做實踐,本文將使用Hadoop的Map/Reduce框架進行簡單的實踐操做。java
Hadoop Map/Reduce是一個使用簡易的軟件框架,基於它寫出來的應用程序可以運行在由上千個商用機器組成的大型集羣上,並以一種可靠容錯的方式並行處理上T級別的數據集。git
一個Map/Reduce 做業(job) 一般會把輸入的數據集切分爲若干獨立的數據塊,由 map任務(task)以徹底並行的方式處理它們。框架會對map的輸出先進行排序, 而後把結果輸入給reduce任務。一般做業的輸入和輸出都會被存儲在文件系統中。 整個框架負責任務的調度和監控,以及從新執行已經失敗的任務。apache
一般,Map/Reduce框架和分佈式文件系統是運行在一組相同的節點上的,也就是說,計算節點和存儲節點一般在一塊兒。這種配置容許框架在那些已經存好數據的節點上高效地調度任務,這可使整個集羣的網絡帶寬被很是高效地利用。windows
Map/Reduce框架由一個單獨的master JobTracker 和每一個集羣節點一個slave TaskTracker共同組成。master負責調度構成一個做業的全部任務,這些任務分佈在不一樣的slave上,master監控它們的執行,從新執行已經失敗的任務。而slave僅負責執行由master指派的任務。網絡
應用程序至少應該指明輸入/輸出的位置(路徑),並經過實現合適的接口或抽象類提供map和reduce函數。再加上其餘做業的參數,就構成了做業配置(job configuration)。而後,Hadoop的 job client提交做業(jar包/可執行程序等)和配置信息給JobTracker,後者負責分發這些軟件和配置信息給slave、調度任務並監控它們的執行,同時提供狀態和診斷信息給job-client。app
注:以上Hadoop Map/Reduce摘自hadoop官方介紹,地址:http://hadoop.apache.org/docs/r1.0.4/cn/mapred_tutorial.html框架
1.windows下hadoop開發環境:參見《hadoop(01)、windows平臺下hadoop環境搭建》dom
2.IDEA 開發編輯器編輯器
3.下載一個部小說(本文使用著名小說:三國演義)
4.上一篇中的項目基礎,碼雲地址:本文源碼碼雲地址:https://gitee.com/MaxBill/hadoop
1.啓動hdfs服務
2.編寫WordCount程序(它能夠計算出指定數據集中指定單詞出現的次數)
官方的例子是統計單詞的,比較簡單,本文則使用分詞器對三國演義的指定詞頻進行統計。在上篇《hadoop(02)、使用JAVA API對HDFS進行基本操做》的基礎上,打開項目,在pom文件中添加分詞的依賴:
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>ik-analyzers</artifactId>
<version>5.1.0</version>
</dependency>
3.開始詞頻統計編碼
主要有如下幾個步驟:
<1>.上傳三國演義小說(分詞數據集)到HDFS中
<2>.編寫統計詞頻代碼
<3>.添加分詞器
<4>.統計指定的詞頻
主要編碼以下:
package com.maxbill.hadoop.reduce; import org.apache.hadoop.fs.Path; import org.apache.hadoop.mapred.FileInputFormat; import org.apache.hadoop.mapred.FileOutputFormat; import org.apache.hadoop.mapred.JobClient; import org.apache.hadoop.mapred.JobConf; import java.util.UUID; /** * @功能 * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 * @時間 14:39 * @備註 WordCountV1 */ public class WordCountV1 { private final static String userPath = "/user/Administrator/"; /** * @功能 單詞統計任務 * @做者 zuoshuai(MaxBill) * @日期 2017/11/16 * @時間 12:12 */ public static void wordCount(String jobName, String inputPath, String outputPath) throws Exception { JobConf jobConf = JobsUtils.getJobsConf(jobName); FileInputFormat.setInputPaths(jobConf, new Path(inputPath)); FileOutputFormat.setOutputPath(jobConf, new Path(outputPath)); JobClient.runJob(jobConf); } /** * @功能 主類測試 * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 */ public static void main(String[] args) throws Exception { String inputPath = userPath + "input/"; String outputPath = userPath + "output/" + UUID.randomUUID().toString().toUpperCase(); //1.建立輸入輸出目錄 //HdfsUtils.mkdir(inputPath); //2.上傳三國演義到Administrator目錄下 //HdfsUtils.uploadFile("D:\\sgyy.txt", inputPath); //3.調用統計任務 wordCount("wordCountV1", inputPath, outputPath); } }
這是詞頻統計及測試主類。
package com.maxbill.hadoop.reduce; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.JobConf; import org.apache.hadoop.mapred.TextInputFormat; import org.apache.hadoop.mapred.TextOutputFormat; /** * @功能 Hadoop Map/Reduce操做工具類 * @做者 zuoshuai(MaxBill) * @日期 2017/11/16 * @時間 12:12 */ public class JobsUtils { private final static String hdfsPath = "hdfs://127.0.0.1:10000"; private final static String jobsPath = "hdfs://127.0.0.1:20000"; /** * @功能 獲取HDFS的配置信息 * @做者 zuoshuai(MaxBill) * @日期 2017/11/16 * @時間 12:12 */ public static Configuration getConfig() { Configuration config = new Configuration(); config.set("fs.default.name", hdfsPath); config.set("mapred.job.tracker", jobsPath); return config; } /** * @功能 獲取HDFS的job配置信息 * @做者 zuoshuai(MaxBill) * @日期 2017/11/16 * @時間 12:12 */ public static JobConf getJobsConf(String jobName) { JobConf jobConf = new JobConf(getConfig()); jobConf.setJobName(jobName); jobConf.setOutputKeyClass(Text.class); jobConf.setOutputValueClass(IntWritable.class); jobConf.setMapperClass(MyMap.class); jobConf.setCombinerClass(MyReduce.class); jobConf.setReducerClass(MyReduce.class); jobConf.setInputFormat(TextInputFormat.class); jobConf.setOutputFormat(TextOutputFormat.class); return jobConf; } }
這是 Hadoop Map/Reduce操做工具類及做業配置
package com.maxbill.hadoop.reduce; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.MapReduceBase; import org.apache.hadoop.mapred.Mapper; import org.apache.hadoop.mapred.OutputCollector; import org.apache.hadoop.mapred.Reporter; import org.wltea.analyzer.core.IKSegmenter; import org.wltea.analyzer.core.Lexeme; import java.io.*; /** * @功能 * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 */ public class MyMap extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); /** * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 * @時間 14:46 */ public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { //未使用分詞器 //String line = value.toString(); //StringTokenizer tokenizer = new StringTokenizer(line); // hile (tokenizer.hasMoreTokens()) { //word.set(tokenizer.nextToken()); //output.collect(word, one); //} //使用分詞器 byte[] btValue = value.getBytes(); InputStream ip = new ByteArrayInputStream(btValue); Reader reader = new InputStreamReader(ip); IKSegmenter iks = new IKSegmenter(reader, true); Lexeme lexeme; while ((lexeme = iks.next()) != null) { //打印所有分詞 //System.err.println(lexeme.getLexemeText()); word.set(lexeme.getLexemeText()); output.collect(word, one); } } }
MAP中使用分詞器
package com.maxbill.hadoop.reduce; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.MapReduceBase; import org.apache.hadoop.mapred.OutputCollector; import org.apache.hadoop.mapred.Reducer; import org.apache.hadoop.mapred.Reporter; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @功能 * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 * @時間 14:46 * @備註 Reduce */ public class MyReduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> { List<String> textList = null; public MyReduce() { textList = new ArrayList<>(); textList.add("孫權"); textList.add("姜維"); } /** * @做者 zuoshuai(MaxBill) * @日期 2017/11/17 * @時間 14:46 */ public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { int sum = 0; while (values.hasNext()) { sum += values.next().get(); } output.collect(key, new IntWritable(sum)); String keyStr = new String(key.toString()); boolean isHas = textList.contains(keyStr); if (isHas) { System.out.println(">>>>>" + keyStr + " [" + sum + "]"); } } }
過濾指定詞頻
4.運行測試主類
咱們從運行測試記過能夠看到,已經統計出孫權和姜維在文中出現的次數。
本文經過使用一些Map/Reduce框架提供的功能,實現的是的利用hadoop hdfs存儲一個數據集,而後使用Hadoop Map/Reduce框架對數據進行簡單的分析處理的一個小實踐。在實踐過程當中也遇到了許多的問題,在查閱官方文檔和網上資料中都一一解決了,對於Map/Reduce還有不少的內容,將在之後的內容中慢慢的學習補充。若有遺漏或者錯誤,歡迎提出!
交流QQ:1370581389
本文源碼碼雲地址:https://gitee.com/MaxBill/hadoop