MapReduce|MapReduce执行流程源码深度剖析(一)
1、分布式计算引擎的核心设计思路 分布式里的核心思路:就是 分而治之 (比如怎么切分和怎么合并)
既然复杂问题,单台计算搞不定,那么就发挥人多力量大的优势:组建一个多服务器组成的集群来完成分布式计算的问题。
核心过程就是:
1、第一阶段:复杂的大任务拆分成多个简单的小任务来进行执行
2、第二阶段:把第一阶段的并行执行的小任务的执行结果进行汇总
MapReduce:一句话讲就是分而治之+并行计算
HDFS:一句话总结,就是分散存储+冗余存储
但是,把单机计算程序,扩展成分布式计算应用程序,会遇到非常多的问题:
- 数据存储的问题,首先需要搞定海量数据存储的问题。
- 运算逻辑至少要切分为两个阶段,一个是怎么并发计算,还有就是怎么汇聚结果
- 这两个阶段如何启动执行,和如何配合
- 运算程序怎么写,才能保证大数据量的问题,移动计算还是移动数据(其实就是数据找程序,还是程序找数据)?
- 如何分配两个阶段的执行计划
- 如何管理计算过程中的中间状态,容错怎么办,例如网络io的一些问题?
- 如何监控和跟踪任务的执行?
- 出错如何处理,抛异常还是重试
2、MapReduce的诞生 MapReduce最早是由Google公司研究提出的一种面向大规模数据处理的并行计算模型和方法。Google公司设计MapReduce的初衷主要是为了解决其搜索引擎中大规模网页数据的并行化处理。Google公司发明了MapReduce之后首先用其重新改写了其搜索引擎中的Web文档索引处理系统。但由于MapReduce可以普遍应用于很多大规模数据的计算问题,因此自发明MapReduce以后,Google公司内部进一步将其广泛应用于很多大规模数据处理问题。Google公司内有上万个各种不同的算法问题和程序都使用MapReduce进行处理。
2003年和2004年,Google公司在国际会议上分别发表了两篇关于Google分布式文件系统和MapReduce的论文,公布了Google的GFS和MapReduce的基本原理和主要设计思想。
Hadoop的思想来源于Google的几篇论文,Google的那篇MapReduce论文里说:Our abstraction is inspired by the map and reduce primitives present in Lisp and many other functional languages。这句话提到了MapReduce思想的渊源,大致意思是,MapReduce的灵感来源于函数式语言(比如Lisp)中的内置函数map和reduce。函数式语言也算是阳春白雪了,离我们普通开发者总是很远。简单来说,在函数式语言里,map表示对一个列表(List)中的每个元素做计算,reduce表示对一个列表中的每个元素做迭代计算。它们具体的计算是通过传入的函数来实现的,map和reduce提供的是计算的框架。不过从这样的解释到现实中的MapReduce还太远,仍然需要一个跳跃。再仔细看,reduce既然能做迭代计算,那就表示列表中的元素是相关的,比如我想对列表中的所有元素做相加求和,那么列表中至少都应该是数值吧。而map是对列表中每个元素做单独处理的,这表示列表中可以是杂乱无章的数据。这样看来,就有点联系了。在MapReduce里,Map处理的是原始数据,自然是杂乱无章的,每条数据之间互相没有关系;到了Reduce阶段,数据是以key后面跟着若干个value来组织的,这些value有相关性,至少它们都在一个key下面,于是就符合函数式语言里map和reduce的基本思想了。
3、MapReduce架构设计概述 MapReduce其实就是责任链设计模式的典型实现!
MapReduce在设计之初,认为不管多复杂的设计模型,不管数据在哪里,存储在哪里,都应该可以使用这个框架执行相关的任务计算,也就是设计之处就要做到通用型。根据这个设计思想,然后开始开发,然后执行了规范,让用户遵循着我们的规范,就可以顺利的编写对应的业务逻辑
MapReduce的架构设计类似于责任链设计模式,每个组件发挥自己的作用。串联起来完成一个完整的分布式应用程序的执行。
接下来让我们看看MapReduce的运行流程:
文章图片
3.1 MapTask的并行度决定机制 假设现在默认的数据块大小是128M,我现在有一个300M的文件,请问,启动几个MapTask?如果是260M呢,启动几个MapTask?
文章图片
3.2 MapTask的并行度决定机制 这里他是我们手动指定的,默认其实就是一个
4、MapReduce运行原理详解
文章图片
1、假设我们的数据是放在HDFS里面的,HDFS和MapReduce是息息相关的一个东西
2、一个文件的切片就是一个FileSplit,会根据我上面讲的切片机制,将数据切分成一个个的split
3、每一个文件切片就会启动一个MapTask,其中的map方法写出去之后,ReduceTask的reduce的方法接收之前,这中间的操作叫shuffle
4、启动map方法写出去之后,会打上分区标记,分区个数和reduceTask是一样的
5、然后就会把我们map写出去的key-value键值对,输出到一个首尾相连的字节数组中(就是环形缓冲区)
6、环形缓冲区默认是100M,当Map的数据量比较大达到100M的时候写出去,这个时候不能写了啊,就阻塞了,因为刷写磁盘是需要时间的,因为磁盘写是比较慢的,所以我们是不是可以写一半的时候再把数据写出去,例如百分之80的时候开始往外溢写,然后剩余百分之20还可以继续写进来。
7、然后在溢写之前会进行一个排序的操作(快速排序),当溢写的文件很多,那么最后会把这些多个spill文件生成为1个文件,这个文件是有序的,首先是分区有序,然后数据有序,并且还有一个索引文件
8、当mapTask大部分都执行完成的时候,reduceTask就会开始执行了。
9、reduceTask开始执行的,首先根据索引文件,将每个MapTask属于自己分区的数据,拉取过来到缓冲(默认也是100M)当中,然后对这些数据进行排序,这个时候就不会对分区进行排序了,因为这些数据就是我这个分区的数据,必然就不需要进行排序了
【MapReduce|MapReduce执行流程源码深度剖析(一)】10、如果内存中不够装满所有的数据,这个时候就会把数据溢写成一个个的小文件,然后就会把数据再进行一个归并排序合并成一个大文件,然后交给reduce方法执行
推荐阅读
- CVE-2020-16898|CVE-2020-16898 TCP/IP远程代码执行漏洞
- 字符串拼接成段落,换行符(\n)如何只执行n-1次
- 迅捷流程图制作软件的使用方法!
- Python专栏|数据分析的常规流程
- Hadoop|Hadoop MapReduce Job提交后的交互日志
- R语言|R语言 函数
- 2018-03-11|2018-03-11 存储过程
- 简述JavaEE学习流程
- 2.关于OpenGL|2.关于OpenGL 坐标系以及渲染流程
- Java并发编程|Java并发编程 - 深入剖析ReentrantLock之非公平锁加锁流程(第1篇)