Mapreduce是一个分布式运算程序的编程框架,是用户开发"基于hadoop的数据分析应用"的核心框架
Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上。
一个完整的mapreduce程序在分布式运行时有三类实例进程:
1.MRAppMaster:负责整个程序的过程调度及状态协调
2.mapTask:负责map阶段的整个数据处理流程
3.ReduceTask:负责reduce阶段的整个数据处理流程
示例代码:
package com.gcxzflgl.hadoopData.mr.wc;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
* KEYIN 默认情况下,是mr框架读到一行数据的起始偏移量
* VALUEIN 默认情况下,是mr框架读到一行文本内容的值
*
* KEYOUT 用户自定义逻辑处理完成之后的key 单词 String
* VALUEOUT 用户自定义逻辑处理完成之后的value 单词 Integer
* @author Administrator
*
*/
public class WordcountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* 每次读取一行
*/
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//将mastask传递给我们的文本内容转换成string
String line = value.toString();
//按照空格切分单词
String[] words = line.split(" ");
//将单词输出为<单词,1>
for(String word : words) {
//将单词作为key,次数1作为value,以便于后续数据分发reduce task
context.write(new Text(word), new IntWritable(1));
}
}
}
package com.gcxzflgl.hadoopData.mr.wc;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
* KEYIN VALUEIN 对应mapper输出的KEYOUT VALUEOUT类型对应
* KEYOUT VALUEOUT 是自定义reduce逻辑处理结果的输出数据
* @author Administrator
*
*/
public class WordcountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 入参key,是一组相同单词kv对的key
* <a,1><a,1><a,1><a,1><a,1>
* <b,1><b,1><b,1><b,1><b,1><b,1><b,1>
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
//当前一组的数量和
int count = 0;
for(IntWritable value : values) {
count += value.get();
}
context.write(key, new IntWritable(count));
}
}
package com.gcxzflgl.hadoopData.mr.wc;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/**
* 相当于yarn集群的客户端
* 封装mr程序相关运行参数,指定jar包,提交给yarn
* @author Administrator
*
*/
public class WordcountDriver {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
// conf.set("mapreduce.framework.name", "yarn");
// conf.set("yarn.resourcemanager.hostname","192.168.227.128" );
Job job = Job.getInstance(conf);
//指定本程序的jar包所在的本地路径
job.setJarByClass(WordcountDriver.class);
//指定本业务job要使用的mapper、Reducer业务类
job.setMapperClass(WordcountMapper.class);
job.setReducerClass(WordcountReducer.class);
//指定mapper输出数据的kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//指定最终输出的数据kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//指定job的输入原始文件所在的目录以及输出结果
FileInputFormat.setInputPaths(job, new Path("/wordcount/input"));
FileOutputFormat.setOutputPath(job, new Path("/wordcount/output"));
//将job相关配置参数,以及job所用的java类所在的jar包,提交给yarn
//job.submit();
boolean res = job.waitForCompletion(true);
System.exit(res?0:1);
}
}
文字叙述简易流程(shuffle过程后期发布):
1.job在提交之前做了很多处理,首先先查看下待处理的数据信息,根据自己的参数配置,形成一个任务分配规划
2.根据任务分配规划(job.split,job.xml,wc.jar)和待处理的文件提交给yarn
3.yarn会查看哪些机器比较空闲找一个最空闲的机器把mrAppMaster启动起来
4.mrAppMaster启动后根据本次job的描述信息,计算出需要好的mapTask实例数量,然后向集群申请启动相应数量的mapTask进程,mapTask启动后,根据给定的数据切片(后期发布)范围进行数据处理
5.根据mapTask去读取一行数据,先是通过inputFormat读取一行的数据返回我们自己定义的WordcountMapper.class,并且通过收集器中outputCollector输出到本地是已经排好序且分区的(后期发布Shuffle)
6.待全部收集完毕后,这时mrAppMaster通知reduceTask会读取分区且排好序的文件,一组一组的读进去,通过我们自定义的WordcountReducer.class写出去,在经过outputFormat组件生成part-r-00000这样的文件