MapReduce是一种分布式计算模型,由Google提出,解决海量数据运算的问题。它由Map和Reduce两种函数组成。Map即映射,将HDFS或数据库中的信息提取出来,按照key-value的形式输送给Reduce。Reduce即化简,是将Map传送过来的数据按照一定的业务逻辑排序提取,得到输出结果。
MapReduce的执行顺序
Map
1.1读取文件内容,解析成key-value对。
1.2完成业务逻辑,提取需要的数据,形成新的key-value对。
1.3对key-value对进行分区(partition),一个分区对应一个reduce任务,一个reduce的执行结果保存在一个文件中。
1.4对同一个分区的数据排序分组,相同key的value放在一个集合中。
1.5分组后的数据进行规约,规约使得从map到reduce所传输的内容减少,减少了网络传输的耗时。
Reduce
2.1将map传送过来的数据根据分区,根据不同的分区通过网络传输给不同的reduce节点。
2.2对多个map任务的输出进行合并和排序,完成自定义的reduce业务逻辑,处理得到新的key-value对。
2.3将最终结果保存在HDFS的文件中。
关于键值对
函数 | 输入 | 输出 |
Map | (k1,v1) | (k2,v2) |
Reduce | (k2,{v2})(规约后为(k2,v2*)) | (k3,v3)(最终结果) |
自定义Map()
private static class MyMapper extends Mapper<LongWritable, Text, Text, LongWritable>{
Text k2 = new Text();
LongWritable v2 = new LongWritable();
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, LongWritable>.Context context)
throws IOException, InterruptedException {
//写业务逻辑,并将<k2,v2>写入context
}
}
自定义Reduce()
private static class MyReducer extends Reducer<Text, LongWritable, Text, LongWritable>{
LongWritable v3 = new LongWritable();
@Override
protected void reduce(Text k2, Iterable<LongWritable> v2s,
Reducer<Text, LongWritable, Text, LongWritable>.Context context) throws IOException, InterruptedException {
//写业务逻辑,将得到的结果<k3,v3>写入context
}
}
驱动代码
Job job = Job.getInstance(new Configuration(), WordCountApp.class.getSimpleName());
job.setJarByClass(XXX.class);
job.setMapperClass(MyMapper.class); //指定自定义Map类
job.setMapOutputKeyClass(Text.class); //指定map输出key类型
job.setMapOutputValueClass(LongWritable.class); //指定Map输出value类型
job.setReducerClass(MyReducer.class); //指定自定义Reduce类
job.setOutputKeyClass(Text.class); //指定输出key类型
job.setOutputValueClass(LongWritable.class);//指定输出value类型
FileInputFormat.setInputPaths(job, input);//指定需要MapReduce处理的文件路径
FileOutputFormat.setOutputPath(job, new Path(output));//指定处理结果的输出路径
try {
job.waitForCompletion(true);//提交job
} catch (Exception e) {
<span style="white-space:pre"> </span>// TODO Auto-generated catch block
System.out.println(e.getMessage());
e.printStackTrace();
}