MapReduce是Hadoop核心框架之一,是一種並行計算的編程模型。當我們利用Hadoop進行大數據處理時,很大一部分工作就是基於MapReduce編寫數據處理程序,所以對於掌握MapReduce執行框架的組件和執行流程非常重要。本文藉助WordCount程序來講述MapReduce執行框架的組件和執行流程。
WordCount程序的作用是統計文本中出現的每個單詞的次數。下面先給出WorkCount程序代碼。
package MapReduceDemo;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
//statistics the number of words
public class WordCountMain {
public static void main(String[] args)throws Exception {
//create job = map + reduce
Configuration conf = new Configuration();
//create Job
Job job = Job.getInstance(conf);
//the entry of job
job.setJarByClass(WordCountMain.class);
//the mapper of job
job.setMapperClass(WordCountMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
//the reducer of job
job.setReducerClass(WordCountReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//input and output
TextInputFormat.setInputPaths(job, new Path(args[0]));
TextOutputFormat.setOutputPath(job, new Path(args[1]));
//submit job
job.waitForCompletion(true);
}
}
package MapReduceDemo;
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class WordCountMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
@Override
protected void map(LongWritable key, Text value,Context context)throws IOException, InterruptedException {
//split string
String data = value.toString();
String[] words = data.split(" ");
for(String word : words){
context.write(new Text(word),new LongWritable(1));
}
}
}
package MapReduceDemo;
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class WordCountReducer extends Reducer<Text, LongWritable, Text, LongWritable>{
@Override
protected void reduce(Text arg0, Iterable<LongWritable> arg1,Context arg2)throws IOException,InterruptedException {
long sum = 0;
for(LongWritable a : arg1){
sum += a.get();
}
arg2.write(arg0, new LongWritable(sum));
}
}
下面我們就以WordCount程序的執行流程來闡述MapReduce執行的幾個階段和所需的組件。
第一階段:以指定格式從HDFS上讀取數據。
要進行數據處理的第一步當然是讀取數據,並且爲了方便進行數據處理,數據必須以特定的某種格式進行讀取。在MapReduce中InputFormat類就是讀取數據的組件。我們知道MapReduce的核心思想是“分而治之”,所以一份大數據就必須要分成多份小數據來處理,而InputFormat類也擔當將大數據分塊的任務。下面是InputFormat類的職責。
(1)以某種格式讀取數據。
(2)將讀取的一份大數據分成邏輯意義上完整的多個塊,其中每一個塊是一個Mapper的輸入。
(3)提供一個RecordReader類,用於將Mapper的輸入(即第二中的塊)轉化爲若干條輸入記錄。
Hadoop提供了一些常用的InputFormat類,每一個InputFormat類都採用特定的格式讀取數據並分塊。下面給出三個常用的InputFormat類。
InputFormat類 | 描述 | 鍵 | 值 |
TextInputFormat | 對文本文件一行一行的讀取 | 當前行的偏移量 | 當前行內容 |
KeyValueInputFormat | 將行解析爲鍵值對 | 行內首個製表符前的內容 | 行內其餘內容 |
SequenceFileInputFormat | 專用於Hadoop的高性能的二進制格式 | 用戶定義 | 用戶定義 |
在WordCount中,我使用的是TextInputFomat類。HDFS上的源數據如下。
I Love Beijing
I Love China
Beijng is the capital of China
經過TextInputFomat類的讀取和分塊(我們假設有兩個分塊),以下是輸入到每個Mapper中的鍵值對。
第一個Mapper的輸入: 0:I love Beijing
第二個Mapper的輸入: 0:I love China 14:Beijing is the capital of China
第二階段:在Mapper中處理每一個鍵值對
怎麼處理鍵值對完全是由用戶定義的,由於WordCount程序的任務是求每個單詞的個數,所以我們就對值進行分詞處理了。下面是每一個Mapper的輸出。
第一個Mapper的輸出: I:1,Love:1,Beijing:1
第二個Mapper的輸出: I:1,Love:1,China:1,Beijing:1,is:1,the:1,capital:1,of:1,China:1
第三階段:對Mapper的輸出進行合併、分區和排序處理之後作爲Reducer的輸入。
每一個Mapper的輸出要傳輸到Reducer中進行處理,在第二個Mapper的輸出中,我們發現有兩個 China:1要進行傳輸,我們能不能把本來要單獨進行兩次傳輸的鍵值對改進成一次傳輸,這樣做的目的就是減少網絡帶寬。在Hadoop中有一個Combiner類就是做這種改進的,它把具有相同主鍵的鍵值對合並在一起成爲一個新的鍵值對,新鍵值對的主鍵還是原來的主鍵,值變爲一個列表,列表中的元素爲原來每一個鍵值對的值。如上述的兩個 China :1 可以合併成 China:[1,1]。
一個鍵值對放在哪個Reducer節點上進行處理是有關係的,爲了避免不同Reducer節點的數據相關性,我們要將具有相同主鍵的鍵值對放在同一個Reducer節點上進行處理。比如第一個Mapper輸出的 I:1 和第二個Mapper輸出的 I:1就要放在同一個Reducer節點上處理。Hadoop提供的Partitioner類就是起這個作用的。下圖是每一個鍵值對的分區結果。
鍵值對進入Reducer節點之後,在每一個Reducer節點內部,會對所有鍵值對進行一個排序。排序默認是以主鍵進行升序的,當然用戶可以自己定義排序操作,這需要重載Hadoop中的Sort類接口函數。在WordCount程序中我們使用默認排序。
第四階段:在Reducer中處理並以指定格式輸出最後結果。
Reducer主要是做一些整理和進一步的處理,其中的邏輯主要由用戶決定,用戶需要重載其reduce()方法。最後結果的輸出和源數據的輸入一樣都有格式要求,Hadoop中的OutputFormat類就提供以指定格式進行輸出的功能。下面介紹幾個常用的OutputFormat類。
OutputFormat | 描述 |
TextOutputFormat | 一行一行輸出 |
SequenceFileOutputFormat | 二進制文件 |
NullOutputFormat | 忽略其輸入值 |
Beijing 2
China 2
I 2
capital 1
is 1
love 2
of 1
the 1
到此,本文的內容介紹完了,本文對MapReduce執行框架的組件和執行流程的見解有偏頗之處,請不吝賜教。
獲取更多幹貨請關注微信公衆號:追夢程序員。