MapReduce基本原理
MapReduce是一種需要在Hadoop集羣上執行的分析程序,也就是說它可以分析的就是在HDFS上所保存的相關數據,在之前見到過一個單詞統計程序,實際上現在也可以自己利用MapReduce來實現這樣的單詞統計程序。
· 如果要想對數據進行分析,則需要有一個輸入的數據信息存在,那麼這個信息就要求保存在HDFS上;
在整個的處理過程裏面,只有Map階段以及Reduce階段才需要開發人員進行具體的編寫處理操作,而其它的開發步驟都會由Hadoop幫助用戶自己完成,同時用戶還需要去分配一個Job用於執行MapReduce。
在Java中編寫Map處理
導入相應的Hadoop開發包
1、所有的Mapper的處理類都需要繼承一個父類:org.apache.hadoop.mapreduce.Mapper,這個類的定義如下:
在通過HDFS讀取數據的時候,每一次執行的Mapper接收的都是一行行的數據;
org.apache.hadoop.mapreduce.Mapper<KEYIN,VALUEIN,KEYOUT,VALUEOUT>
具體參數的作用如下:
KEYIN:輸入數據的KEY;
VALUEIN:表示真實輸入的數據,現在所需要的內容;
KEYOUT:輸出的Map中KEY類型;(Haddop中把字符串使用Text描述;)
VALUEOUT:輸出的Map中的Value的類型;(Hadoop中把數字使用IntWritable類型描述)
private static class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
@Override
protected void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
// 讀取每一行的數據,Map是根據換行作爲讀取的分割符;
String str = value.toString() ; // 取的每一行的內容
// 所有的單詞要求按照空格進行拆分
String result [] = str.split(" "); // 按照空格拆分
// 將本行的數據變爲一組Map的內容
for (int x = 0 ; x < result.length ; x ++) {
context.write(new Text(result[x]), new IntWritable(1)); // 將數據取出
}
}
}
編寫Reduce處理
對Map的數據進行再一次的處理,稱爲Reduce操作,而且一定要記住,在Map處理完成之後會存在有一個排序的操作形式,因爲利用排序可以加快處理形式。
要想實現Reduce處理操作,那麼一定要記住,需要繼承一個父類: Reduce類定義:org.apache.hadoop.mapreduce.Reducer
private static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException,InterruptedException {
int sum = 0 ; // 統計總量
for (IntWritable wri : values) { // 取出所有的統計數據
sum += wri.get() ; // 進行數據的累加處理
}
context.write(new Text(key), new IntWritable(sum));
}
}
定義Job
整個一次的MapReduce執行對於Hadoop而言都相當於啓動了一個作業,也就是說在整個的作業的運行過程之中你需要明確的指定出本作業要使用的Map與Reduce程序的定義。
如果要想定義作業:org.apache.hadoop.mapreduce.Job;
public static void main(String[] args) throws Exception {
if (args.length != 2) { // 現在輸入的參數個數不足,那麼則應該退出程序
System.out.println("本程序的執行需要兩個參數:HDFS輸入路徑 HDFS的輸出路徑");
System.exit(1); // 程序退出
}
Configuration conf = new Configuration() ; // 此時需要進行HDFS操作
String paths [] = new GenericOptionsParser(conf,args).getRemainingArgs() ; // 將輸入的兩個路徑解析爲HDFS的路徑
// 需要定義一個描述作業的操作類
Job job = Job.getInstance(conf, "hadoop") ;
job.setJarByClass(WordCount.class); // 定義本次作業執行的類的名稱
job.setMapperClass(WordCountMapper.class); // 定義本次作業完成所需要的Mapper程序類
job.setMapOutputKeyClass(Text.class); // 定義Map輸出數據的Key的類型
job.setMapOutputValueClass(IntWritable.class); // 定義Map輸出數據的Value的類型
job.setReducerClass(WordCountReducer.class); // 定義要使用的Reducer程序處理類
job.setOutputKeyClass(Text.class); // 最終輸出統計結果的key的類型
job.setOutputValueClass(IntWritable.class); // 最終輸出統計結果的value的類型
// 所有的數據都在HDFS上進行操作,那麼就必須使用HDFS提供的程序進行數據的輸入配置
FileInputFormat.addInputPath(job, new Path(paths[0])); // 定義輸入的HDFS路徑
FileOutputFormat.setOutputPath(job, new Path(paths[1]));// 定義統計結果的輸出路徑
System.exit(job.waitForCompletion(true) ? 0 : 1); // 程序執行完畢後要進行退出
}
如果要想執行定義好的作業不能夠在本地上直接執行,一定要將程序變爲jar文件發送到服務器(Hadoop)上執行。
將項目打包成.jar文件並上傳至服務器中。
hadoop jar MapReduce.jar路徑 要測試的文件路徑 測試結果輸出路徑
隨後打開輸出路徑上的結果文件既可以觀察統計結果。