在hadoop平台中,有一个很重要的组件——MapReduce(hadoop自带的,不用单独安装),它是一个分布式计算框架,该框架提供两个很重要的部件——Mapper和Reducer。
MR的基本执行流程:
从图中,我们可以看出,MR程序从hdfs中读入数据进行分片,形成一个(key,value)键值对传入到map中,经过map程序的处理形成一个(key,{value,value})键值列表传入到reduce中,然后经过reduce的处理在形成一个(key,value)键值对保持到hdfs中(不一定是hdfs,可以是hbase等)。但是,这是一个简单的MR程序的执行流程,在这个简单的执行流程中MapReduce计算框架在背后做了很多默默无闻的工作。接下来我们就来看看其背后工作:
1.split(分片):在分片这个步骤中会用到两个方法InputFormat()和InputSplit(),InputSplit是hadoop定义用来传送个每一个map的数据,但是该数据不是数据本身而是一个数据长度和记录数据位置的数组。而真正要生成map的输入的(key,value)是通过InputFormat方法,因为当数据传输到map中时,他会把数据传输到InputFormat上,然后调用getRecordReader()方法生成RecordReader,再通过createKey()和createValue()方法生成(key,value)。
2.在经过map程序处理后形成的是(key,{value,value})键值对列表,在这个工程经过了shuffle的过程。
shuffle过程在map端和reduce端都会执行。
(1)在map端的shuffle过程是对结果进行划分(partition),排序(sort),分割(spill),把属于同一个划分的输出合并在一起(merge),写入磁盘,然后按照划分的结果发送给对应的reduce。
(2)reduce端的shuffle过程是把map端传输来的属于同一个划分的输出进行合并,然后进行排序,最后交个reduce进行处理。(三个阶段:map输出,合并排序,执行reduce)
实例如下:
public class MyTest {
public static class MyMap extends Mapper<LongWritable, Text, Text, IntWritable> {
/*
* 在编写MR程序时该方法不是必要的
* 该方法是在task启动开始就调用的(只会调用一次),该方法其实可以看作一个全局处理方法
* 可以把使用的全局变量用改方法进行初始化,获取从作业信息中获取全局变量
*/
protected void setup(Context context) throws IOException ,InterruptedException {
}
/*
* 在编写MR程序时该方法是必须要的
*/
protected void map(LongWritable key, Text value, Context context) throws IOException ,InterruptedException {
}
/*
* 在编写MR程序时该方法不是必要的
* 该方法和setup方法的作业相似,但是该方法是在task销毁前执行的,主要用于做一些清扫工作
*/
protected void cleanup(Context context) throws IOException ,InterruptedException {
}
}
public static class MyReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
/*
* 在编写MR程序时该方法不是必要的
* 该方法是在task启动开始就调用的(只会调用一次),该方法其实可以看作一个全局处理方法
* 可以把使用的全局变量用改方法进行初始化,获取从作业信息中获取全局变量
*/
protected void setup(Context context) throws IOException ,InterruptedException {
}
/*
* 在编写MR程序时该方法是必须要的
*/
protected void reduce(Context arg2) throws IOException ,InterruptedException {
}
/*
* 在编写MR程序时该方法不是必要的
* 该方法和setup方法的作业相似,但是该方法是在task销毁前执行的,主要用于做一些清扫工作
*/
protected void cleanup(Context context) throws IOException ,InterruptedException {
}
}
public static void main(String[] args) {
}
}