[2] - mapreduce的shuffle流程详解

一、MapReduce执行全流程(包含shuffle)

1、mr执行流程图

1
mapreduce流程图2
2、流程文字描述:
1、首先准备好待处理文本(一般是存储在hdfs上的日志文件等)
2、客户端提交前,先获取待处理数据的信息,根据参数配置,形成一个任务分配的规划(数据切片), 有几个切片就对应那几个map
3、提交切片信息
4、计算出maptask的数量
5、存在一个inputFormat父类,hadoop使用的是FileInputFormat去继承InputFormat然后将文件切片数据读入到Mapper端,FileInputFormat类中定义了一个RecorderReader,按行读入mapper
6、1).在Mapper端进行一个逻辑运算,通过k,v对对获取到的文本进行按需求切分,然后按需求输出;
2).存在一个outputCollector将处理好的内容写入到环形缓冲区,默认大小为100m,按0.8溢出,
溢出前先分区(key的hashCode进行%reducTask运算)在排序(对key进行排序,实现一个接
口WrtitaleComparable), 在进行一个归并排序,通过outputFormat将各个分区内的数据块整合
成多个文件溢出到本地磁盘,
3).其实分区排序后还要一个combiner,每个map下的k,v对的整合,减少reduce端的io,对相同key的
数据进行一个 统计, 减少reduce端io,combinner是在reducer端之前操作的,也是继承的Reducer,作用
是提高reduce端的效率
7、输出到reducer端,还要经历一个环形缓冲区,同时也是按到80%溢出文件到reducer,
将相同的key进行归并排序,在分组,将相同key的value装进同一个集合(累加).在对value进行求和
8、reducer将文件输出到本地磁盘

注意:环形缓冲区的工作流程 分区数据块读入内存, 先按顺序写入环形缓冲区到了80%在进行溢写文件,
第二次数据块写入的时候, 在反向读入内存,依然是到了80%在进行溢写文件,溢写前要进行分区和排序

**

二、MR的shuffle机制

1、概述
mapreduce中,map阶段处理的数据如何传递给reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle;shuffle:洗牌、发牌——(核心机制:数据分区,排序,缓存);具体来说:就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key进行了分区和排序;
2、shuffle流程图(按自己理解画的)按自己理解画的流程图

shuffle是MR处理流程中的一个过程,它的每一个处理步骤是分散在各个map task和reduce task节点上完成的,整体来看,分为3个操作:
  • 分区partition 属于map Task阶段
  • Sort根据key排序 属于reduce Task阶段
  • Combiner进行局部value的合并
    - 3、注意点总结
    1.有几个数据切片 就有几个mapTask,一个数据块的大小默认为128M可以根据实际情况进行修改
    2.数据是以<k,v>对的形式进行传输的,通过FileInputFormat类将一行文本读入内存,map端通过
    该类中的RecorderReader将获取的一行文本转换为key,value对,紧接着在map端进行业务流程.
    3.环形缓冲区特点:默认大小为100M,数据读入达到80%时开始溢写文件
    一次溢写完毕,在溢写点,输入数据,这样循环输入输出
    4.在溢写文件之前,会做两件事:1).分区; 2).排序
    分区是根据k的哈希值与reduceTask的数量的取模运算进行分区
    一个分区代表一个文件,不同mapTask中的相同key的分区在输出到
    reduce之前会有一个归并排序.<hello,1><hello,1><java,1>---->
    <hello,<1,1>>,<java,1>
    5.reduceTask对输入得数据进行Combiner累加,通过outputFormat输出到本地磁盘
    reduceTask的数量根据分区的数量决定.一般ReduceTask的数量大于等于分区数才有意义,
    大于的部分不会有数据

MR应用程序驱动类模板代码整理

以WordCount为例:
class A_Driver{
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		//1.获取配置信息
		Configuration conf = new Configuration();
		
		//2实例化Job类,并且把配置信息传给job
		Job job = Job.getInstance(conf);
		//3.通过反射机制,加载诸类的位置
		job.setJarByClass(A_Driver.class);//A_Driver为驱动类的名称
		
		//4.设置mapper和reudcer类
		job.setMapperClass(A_Mapper.class);
		job.setReducerClass(A_Reducer.class);
		job.setCombinerClass(A_Combiner.class);
		
		//5.设置map的输出
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		//6.设置reduce的输出
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		
		
		//7.设置输入输出路径:生产环境一般为hdfs, 或者通过打jar包的形式拿到hdfs上执行
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		//提交任务
		boolean result = job.waitForCompletion(true);
		System.exit(result?0:1);
		
	}
}

猜你喜欢

转载自blog.csdn.net/murphyZ/article/details/88050938
今日推荐