Mapreduce原理及应用

Mapreduce原理

MapReduce(以下简称MR)是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)“和"Reduce(归约)”,是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。 当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归约)函数,用来保证所有映射的键值对中的每一个共享相同的键组。

MR主要思想:分久必合

MR是由两个阶段组成
Map端
Reduce端

MR核心思想:“相同”的key为一组,调用一次reduce方法,方法内迭代这一组数据进行计算

MapReduce分布式计算原理

MR在计算之前,会将HDFS上的文件划分切片
默认大小 block = split切片 = map task 注:split会比block大几kb或小几kb,因为block是严格按照字节切分,防止数据乱码,会将block下一块的第一行数据也添加进去;

Shuffle write阶段

Map task将处理后的每一条记录打上标签,打标签的目的就是为让这一条知道将来被哪一个redcuce task处理,然后进入buffer后,每一条记录是由三部分组成:1、分区号 2、key 3、value,Map task往buffer中写入过程中,一旦写入到80M,此时会将这80M的内存封锁,封锁后,会对内存中的数据进行combiner(小聚合),然后进行排序,将相同分区的数据放到一起,并且分区的数据是有序的,以上的combiner以及排序完成后,就开始溢写数据到磁盘上,此时的磁盘文件就是一个根据分区号,分好区的,并且内部有序的文件combiner、sort、spill每进行一次溢写,就会产生一个磁盘小文件

Map task计算完毕后,会将磁盘上的小文件合并成一个大文件,在合并的时候会使用归并排序的算法,将各个小文件合并成一个有序的大文件

Shuffle read阶段

从map端读取相应的分区数据,将分区数据写入到内存中,内存满了就会溢写,溢写之前会排序,当把所有的数据取过来之后,会将溢写产生的磁盘小文件合并 排序成有序的大文件,然后 每一个大文件启动一个Reduce task进行计算,然后将结果输出到结果文件中,最后返回给客户端。
在这里插入图片描述

MapReduce的核心程序运行机制

(1) 一个 MR 程序启动的时候,最先启动的是 MRAppMaster, MRAppMaster 启动后根据本次 job 的描述信息,计算出需要的 maptask 实例数量,然后向集群申请机器启动相应数量的 maptask 进程
(2) maptask 进程启动之后,根据给定的数据切片(哪个文件的哪个偏移量范围)范围进行数 据处理,主体流程为:
A、 利用客户指定的 inputformat 来获取 RecordReader 读取数据,形成输入 KV 对
B、 将输入 KV 对传递给客户定义的 map()方法,做逻辑运算,并将 map()方法输出的 KV 对收 集到缓存
C、 将缓存中的 KV 对按照 K 分区排序后不断溢写到磁盘文件 (超过缓存内存写到磁盘临时文件,最后都写到该文件,ruduce 获取该文件后,删除 )
(3) MRAppMaster 监控到所有 maptask 进程任务完成之后(真实情况是,某些 maptask 进程处理完成后,就会开始启动 reducetask 去已完成的 maptask 处数据),会根据客户指 定的参数启动相应数量的 reducetask 进程,并告知 reducetask 进程要处理的数据范围(数据分区)
(4) Reducetask 进程启动之后,根据 MRAppMaster 告知的待处理数据所在位置,从若干台 maptask 运行所在机器上获取到若干个 maptask 输出结果文件,并在本地进行重新归并排序, 然后按照相同 key 的 KV 为一个组,调用客户定义的 reduce()方法进行逻辑运算,并收集运
算输出的结果 KV,然后调用客户指定的 outputformat 将结果数据输出到外部存储

Mapreduce应用

MapReduce-WordCount示例编写及编码规范

(1) 程序有一个 main 方法,来启动任务的运行,其中 job 对象就存储了该程序运行的必要 信息,比如指定 Mapper 类和 Reducer 类

public class WC {
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		Configuration conf = new Configuration(true);


		Job job = Job.getInstance(conf);
		//设置当前main函数所在类
		job.setJarByClass(WC.class);
		job.setJar("d:/HDFS/wc.jar");

		//设置输入路径
		FileInputFormat.setInputPaths(job, "/input/wc.txt");
		//设置输出路径
		Path outputPath = new Path("/output");
		FileSystem fs = outputPath.getFileSystem(conf);
		if(fs.exists(outputPath)){
			fs.delete(outputPath,true);
		}
		FileOutputFormat.setOutputPath(job, outputPath);

		//设置Map class
		job.setMapperClass(WCMapper.class);
		//设置map输出key、value的类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);

		//设置reduce class
		job.setReducerClass(WCReduce.class);

		job.setNumReduceTasks(2);

		job.waitForCompletion(true);
	}
}

job.setMapperClass(TokenizerMapper.class);
job.setReducerClass(IntSumReducer.class);
(2) 该程序中的 TokenizerMapper 类继承了 Mapper 类
(3) 该程序中的 IntSumReducer 类继承了 Reducer 类

MapReduce 程序的业务编码分为两个大部分,一部分配置程序的运行信息,一部分 编写该 MapReduce 程序的业务逻辑,并且业务逻辑的 map 阶段和 reduce 阶段的代码分别继 承 Mapper 类和 Reducer 类
(1) 用户编写的程序分成三个部分: Mapper, Reducer, Driver(提交运行 MR 程序的客户端)
(2) Mapper 的输入数据是 KV 对的形式( KV 的类型可自定义)
(3) Mapper 的输出数据是 KV 对的形式( KV 的类型可自定义)
(4) Mapper 中的业务逻辑写在 map()方法中
(5) map()方法( maptask 进程)对每一个<K,V>调用一次

package com.hpe.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;
import org.apache.hadoop.util.StringUtils;

public class WCMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
	Text myKey = new Text();
	IntWritable myValue = new IntWritable(1);
	@Override
	protected void map(LongWritable key, Text value, Context context)
			throws IOException, InterruptedException {
		System.out.println(key+"==========");
//		value.toString().split(" ")
		String[] words = StringUtils.split(value.toString(), ' ');
		for (String word : words) {
			myKey.set(word);
			context.write(myKey,myValue);
		}
	}
}

(6) Reducer 的输入数据类型对应 Mapper 的输出数据类型,也是 KV
(7) Reducer 的业务逻辑写在 reduce()方法中
(8) Reducetask 进程对每一组相同 k 的<k,v>组调用一次 reduce()方法

package com.hpe.mr.wc;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;


public class WCReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{
		 int sum = 0;
		 for (IntWritable value : values) {
			sum += value.get();
		}
		 context.write(key, new IntWritable(sum));
	}

}

(9) 用户自定义的 Mapper 和 Reducer 都要继承各自的父类
(10) 整个程序需要一个 Drvier 来进行提交,提交的是一个描述了各种必要信息的 job 对象

WordCount 的业务逻辑:

1、 maptask 阶段处理每个数据分块的单词统计分析,思路是每遇到一个单词则把其转换成 一个 key-value 对,比如单词 hello,就转换成<’hello’,1>发送给 reducetask 去汇总
2、 reducetask 阶段将接受 maptask 的结果, 来做汇总计数

猜你喜欢

转载自blog.csdn.net/qq_40262690/article/details/83184624
今日推荐