MapReduce(一):入門級程式wordcount及其分析

fan_rockrock發表於2015-09-15

1.MapReduce處理過程

   map函式接收一個<key,value>形式的輸入,然後同樣產生一個<key,value>形式的中間輸出,reduce函式接收一個如<key,(list of values)>形式的輸入,然後對這個value集合進行處理,每個reduce產生0或1個輸出,reduce的輸出也是<key,value>形式的。


 (1). map任務處理
          1.1 讀取輸入檔案內容,解析成key、value對。對輸入檔案的每一行,解析成key、value對。每一個鍵值對呼叫一次map函式。
          1.2 寫自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。
          1.3 對輸出的key、value進行分割槽。
          1.4 對不同分割槽的資料,按照key進行排序、分組。相同key的value放到一個集合中。
          1.5 (可選)分組後的資料進行歸約。
(2).reduce任務處理
          2.1 對多個map任務的輸出,按照不同的分割槽,通過網路copy到不同的reduce節點。
          2.2 對多個map任務的輸出進行合併、排序。寫reduce函式自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。
          2.3 把reduce的輸出儲存到檔案中。

2.特別資料型別簡介

    Hadoop提供瞭如下內容的資料型別,這些資料型別都實現了WritableComparable介面,以便用這些型別定義的資料可以被序列化進行網路傳輸和檔案儲存,以及進行大小比較。

    BooleanWritable:標準布林型數值

    ByteWritable:單位元組數值

    DoubleWritable:雙位元組數

    FloatWritable:浮點數

    IntWritable:整型數

    LongWritable:長整型數

    Text:使用UTF8格式儲存的文字

    NullWritable:當<key,value>中的key或value為空時使用

3.原始碼呈現

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
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 {
	//Map方法
	//輸入型別為<longWritable,Text>
	//輸出型別為<Text,IntWritable>
    public static class WCMapper extends Mapper<LongWritable,Text,Text,IntWritable>
    {
    	private final static IntWritable one=new IntWritable(1);
    	private Text text=new Text();
    	@Override
		protected void map(LongWritable key, Text value,Context context)
				throws IOException, InterruptedException 
    	{
    		String line=value.toString();
    		String []words=line.split("	");//製表符分離
    		for(String w:words)
    		{
    			text.set(w);
    			context.write(text, one);
    		}
		}
    }
    
    //reduce方法
	public static class WCReducer extends Reducer<Text,IntWritable,Text,IntWritable>
	{
		private IntWritable result=new IntWritable();
		@Override
		protected void reduce(Text key, Iterable<IntWritable>values,Context context)
				throws IOException, InterruptedException {
			int sum=0;
			for(IntWritable v:values)
			{
				sum+=v.get();
			}
			result.set(sum);
			context.write(key, result);
		}
	}
    
	//主函式,基本操作6大步
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException
	{
		
		//構建job物件
		Configuration conf=new Configuration();
		Job job=Job.getInstance(conf, "WordCount");
		
		//設定main方法所在的類
		job.setJarByClass(WordCount.class);
		
		//設定mapper相關屬性
		job.setMapperClass(WCMapper.class);
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		//設定reducer相關屬性
		job.setReducerClass(WCReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		
		//設定檔案輸入輸出
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job,new Path(args[1]));
		
		//提交任務
		System.exit(job.waitForCompletion(true)? 0:1);
	}
}

4.執行流程分析

  1)將檔案拆分成splits,由於測試用的檔案較小,所以每個檔案為一個split,並將檔案按行分割形成<key,value>對,如圖4-1所示。這一步由MapReduce框架自動完成,其中偏移量(即key值)包括了回車所佔的字元數(Windows和Linux環境會不同)。


 2)將分割好的<key,value>對交給使用者定義的map方法進行處理,生成新的<key,value>對,如圖4-2所示。


 3)得到map方法輸出的<key,value>對後,Mapper會將它們按照key值進行排序,並執行Combine過程,將key至相同value值累加,得到Mapper的最終輸出結果。如圖4-3所示。


 4)Reducer先對從Mapper接收的資料進行排序,再交由使用者自定義的reduce方法進行處理,得到新的<key,value>對,並作為WordCount的輸出結果,如圖4-4所示。


相關文章