Hadoop MapReduce数据处理过程以及更多示例

上一篇文章介绍了Hadoop的单机配置以及一个简单的MapReduce示例,今天看看MapReduce处理数据的流程是怎样的。建议阅读本文前,最好能看一下上一篇文章的代码。


上图以上一篇文章的MapReduce示例为例,展示了单机配置下MapReduce的处理流程,由于单机情况下更容易理解处理流程,所以这篇文章以单机处理为例,实际上,分布式配置时,也是这样的流程,只是在每个环节的数据形式有所不同,后面的文章会进行介绍。先来看一下上面的流程。

1.input

该阶段很简单,就是将输入文件中的内容按行分割为key和value的形式。看一下上篇文章中的map方法的参数

protected void map(LongWritable key, Text value, Context context)
这里的key和value,就对应input阶段生成的key和value。

2.Map

Map阶段所做的工作就是我们map方法所做的事情,这是由我们自己定义的,主要对input实现细分和过滤,保留我们需要的数据,以key和value的形式,通过context输出。之前例子中,我们在map方法中取出了每一个单词的首字母,以首字母作为key,数值1作为value进行输出。

3.Shuffle

注意上图中Map输出中所示的B,有两行,也就是说,Map阶段的输出,会有key相同的记录。而且,输出是无序的。在Shuffle阶段,会对map的输出按照key进行合并和排序,然后作为reduce的输入使用。如果使用自定义的类对象作为key,该类可以实现WritableComparable接口,定义自己的排序方式。

4.Reduce

Reduce的过程完成reduce方法所做的事情。我们的示例中将所属key下的1进行了叠加,从而计算出一个字母作为首字母出现的次数。最后结果以key和value的方式输出。

以上就是MapReduce的处理过程,最后说明一下,我们在派生Mapper类和Reducer类时,都分别传入了四个类型参数,他们分别对应Map和Reduce阶段的输入key和value类型以及输出key和value类型。对于基本类型,Hadoop提供了可序列化类,如示例中的LongWritable(对应Long),Text(对应String)等,最好使用这些类,以方便Hadoop在分布式情况下对数据进行处理。


了解了处理流程,这里再给出两个简单示例,方便大家理解。先看第一个示例,我们将英文文章中出现的单词进行排序,使用的输入仍然是上一篇文章中的text。代码如下:

package com.yjp.mapreduce;

import java.io.IOException;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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.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 WordSort {

	// 执行Map
	private static class WordSortMapper 
		extends Mapper<LongWritable, Text, Text, Text> {
		
		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
			String line = value.toString();  
            StringTokenizer token = new StringTokenizer(line);
            while (token.hasMoreTokens()) {
            	String word = token.nextToken();
            	Pattern p = Pattern.compile("[A-Za-z]+");
                Matcher m = p.matcher(word);
                if (m.find()) {
                	context.write(new Text(m.group(0)), new Text());
                }
            }
		}
	}
	
	// 执行Reduce
	private static class WordSortReducer 
		extends Reducer<Text, Text, Text, Text> {
		@Override
		protected void reduce(Text key, Iterable<Text> values, Context context) 
				throws IOException, InterruptedException {
			context.write(key, new Text());
		}
	}
	
	public static void main(String[] args) throws Exception {
		if (args.length != 2) {
			System.err.println("Usage: WordSort <inout path> <output path>");
			System.exit(-1);
		}
		
		// 设置类信息,方便hadoop从JAR文件中找到
		Job job = Job.getInstance();
		job.setJarByClass(WordSort.class);
		job.setJobName("Word Sort");
		
		// 添加输入输出路径
		FileInputFormat.addInputPath(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		// 设置执行Map和Reduce的类
		job.setMapperClass(WordSortMapper.class);
		job.setReducerClass(WordSortReducer.class);
		
		//设置输出数据类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
}
这个例子很简单,上面的流程我们分析过,执行完Shuffle实际上已经完成了归并和排序,所以,我们这个示例,Reduce过程很简单,直接将传递进来的输入进行输出即可。


第二个示例,我们统计一段文字中出现的字母及其数目。了解了流程,这就简单多了,我们只要基于上一篇文章的示例,修改它的map方法即可

@Override
protected void map(LongWritable key, Text value, Context context)
		throws IOException, InterruptedException {
	String line = value.toString();  
    StringTokenizer token = new StringTokenizer(line);
    
    while (token.hasMoreTokens()) {
    	String word = token.nextToken();
    	Pattern p = Pattern.compile("[A-Za-z]+");
        Matcher m = p.matcher(word);
        if (m.find()) {
        	word = m.group(0);
        	for (int i = 0; i < word.length(); i++) {
        		context.write(new Text(word.charAt(i) + ""), one);
        	}
        }
    }
}
代码已上传直github.


猜你喜欢

转载自blog.csdn.net/yjp19871013/article/details/78570907