MapReduce 运行全过程解析
关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料。
前言
前面我们讲了 MapReduce 的编程模型,我们知道他主要分成两大阶段来完成一项任务,一是 map 阶段对我们的数据进行分开计算,第二是 reduce 阶段,对 map 阶段计算产生的结果再进行汇总。
还写了一个非常经典的,类似于Java 中 HelloWorld 一样的 WordCount 代码。今天我们就根据这个代码来阐述整个 MapReduce 的运行过程。
先苦口婆心的告诉你,这个知识点是非常非常非常之重要,之前面的 5 家公司,有 3 家公司都问了这个过程,另外两家问了 Yarn 的运行机制,这是后面会去讲的内容,你必须得懂大体的流程是怎么样子,如果能去研究搞清楚每个细节,那当然最好的。
从数据进如到处理程序到处理完成后输出到存储中,整个过程我们大体分为如下 5 个阶段:
Input Split 或 Read 数据阶段
Input Split,是从数据分片出发,把数据输入到处理程序中。Read 则是从处理程序出发反向来看,把数据从文件中读取到处理程序中来。这个阶段表达的是我们数据从哪里来。这是整个过程的开始。
Map阶段
当数据输入进来以后,我们进行的是 map 阶段的处理。例如对一行的单词进行分割,然后每个单词进行计数为 1 进行输出。
Shuffle 阶段
Shuffle 阶段是整个 MapReduce 的核心,介于 Map 阶段跟 Reduce 阶段之间。在 Spark 中也有这个概念,可以说你理解了这个概念,到时候再学习其他的大数据计算框架原理的时候,会给你带来非常大的帮助,因为他们大多理念是相同的,下面会重点讲解这个过程。
Reduce 阶段
数据经过 Map 阶段处理,数据再经过 Shuffle 阶段,最后到 Reduce ,相同的 key 值的数据会到同一个 Reduce 任务中进行最后的汇总。
Output 阶段
这个阶段的事情就是将 Reduce 阶段计算好的结果,存储到某个地方去,这是整个过程的结束。
整个执行流程图
一图胜千言:
如果看不清晰,我上传了一份完整的在 gayHub 上面,地址:
(https://raw.githubusercontent.com/heyxyw/bigdata/master/bigdatastudy/doc/img/mapreduce/mr-Implementation-process.png)
当然了,不太了解或者刚接触可能一开始看比较懵逼,我刚开始也是。下面我们就一块一块的来拆分讲解,最后差不多就明白了。
Input Split 数据阶段
Input Split 顾明思议,输入分片 ,为什么我们会叫 输入分片呢?因为数据在进行 Map 计算之前,MapReduce 会根据输入文件进行切分,因为我们需要分布式的进行计算嘛,那么我得计算出来我的数据要切成多少片,然后才好去对每片数据分配任务去处理。
每个输入分片会对应一个 Map 任务,输入分片存储的并非数据本身,而是一个分片长度和一个记录数据的位置数据,它往往是和 HDFS 的 block(块) 进行关联的。
假如我们设定每个 HDFS 的块大小是 128M,如果我们现在有3个文件,大小分别是 10M,129M,200M,那么MapReduce 对把 10M 的文件分为一个分片,129M 的数据文件分为2个分片,200M 的文件也是分为两个分片。那么此时我们就有 5 个分片,就需要5个 Map 任务去处理,而且数据还是不均匀的。
如果有非常多的小文件,那么就会产生大量的 Map 任务,处理效率是非常低下的。
这个阶段使用的是 InputFormat 组件,它是一个接口 ,默认使用的是 TextInputFormat 去处理,他会调用 readRecord() 去读取数据。
这也是MapReduce 计算优化的一个非常重要的一个点,**面试被考过**。如何去优化这个小文件的问题呢?
最好的办法:在数据处理系统的最前端(预处理、采集),就将小文件先进行合并了,再传到 HDFS 中去。
补救措施:如果已经存在大量的小文件在HDFS中了,可以使用另一种 InputFormat 组件CombineFileInputFormat 去解决,它的切片方式跟 TextInputFormat 不同,它会将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 Map 任务去处理了。
Map阶段
将 Map 阶段的输出作为 Reduce 阶段的输入的过程就是 Shuffle 。 这也是整个 MapReduce 中最重要的一个环节。
一般MapReduce 处理的都是海量数据,Map 输出的数据不可能把所有的数据都放在内存中,当我们在map 函数中调用 context.write() 方法的时候,就会调用 OutputCollector 组件把数据写入到处于内存中的一个叫环形缓冲区的东西。
环形缓冲区默认大小是 100M ,但是只写80%,同时map还会为输出操作启动一个守护线程,当到数据达到80%的时候,守护线程开始清理数据,把数据写到磁盘上,这个过程叫 spill 。
数据在写入环形缓冲区的时候,数据会默认根据key 进行排序,每个分区的数据是有顺序的,默认是 HashPartitioner。当然了,我们也可以去自定义这个分区器。
每次执行清理都产生一个文件,当 map 执行完成以后,还会有一个合并文件文件的过程,其实他这里跟 Map 阶段的输入分片(Input split)比较相似,一个 Partitioner 对应一个 Reduce 作业,如果只有一个 reduce 操作,那么 Partitioner 就只有一个,如果有多个 reduce 操作,那么 Partitioner 就有多个。Partitioner 的数量是根据 key 的值和 Reduce 的数量来决定的。可以通过 job.setNumReduceTasks() 来设置。
这里还有一个可选的组件 Combiner ,溢出数据的时候如果调用 Combiner 组件,它的逻辑跟 reduce 一样,相同的key 先把 value 进行相加,前提是合并并不会改变业务,这样就不糊一下传输很多相同的key 的数据,从而提升效率。
举个例子,在溢出数据的时候,默认不使用 Combiner,数据是长这样子: <a,1>,<a,2>,<c,4>。 当使用 Combiner 组件时,数据则是: <a,3>,<c,4> 。把 a 的数据进行了合并。
Reduce 阶段
在执行 Reduce 之前,Reduce 任务会去把自己负责分区的数据拉取到本地,还会进行一次归并排序并进行合并。
Reduce 阶段中的 reduce 方法,也是我们自己实现的逻辑,跟Map 阶段的 map 方法一样,只是在执行 reduce 函数的时候,values 为 同一组 key 的value 迭代器。在 wordCount 的例子中,我们迭代这些数据进行叠加。最后调用 context.write 函数,把单词和总数进行输出。
Output 阶段
在 reduce 函数中调用 context.write 函数时,会调用 OutPutFomart 组件,默认实现是 TextOutPutFormat ,把数据输出到目标存储中,一般是 HDFS。
扩展
上面我们只是讲解了大体的流程,这里给大家抛几个问题?也是面试中经常被问到的。
1. 文件切分是怎么切的?一个文件到底会切成几分?算法是怎么样的?
2. Map 任务的个数是怎么确定的?
上面的问题,给大家贴两个链接:
MapReduce Input Split(输入分/切片)详解:
https://blog.csdn.net/dr_guo/article/details/51150278
源码解析 MapReduce作业切片(Split)过程:
https://blog.csdn.net/u010010428/article/details/51469994
总结
MapReduce 的执行流程到这里就大致讲解完成了,希望你也能画出来上面的大图。能够理解到大体的流程,并能掌握关键的环节 Shuffle 。以后你还会在其他的大数据组件上听到这个词。
后面将给大家带来 Yarn 的大致运行机制,然后再为大家讲解 WordCount 运行的整个过程。
敬请期待。
Java 极客技术公众号,是由一群热爱 Java 开发的技术人组建成立,专注分享原创、高质量的 Java 文章。如果您觉得我们的文章还不错,请帮忙赞赏、在看、转发支持,鼓励我们分享出更好的文章。
MapReduce 运行全过程解析的更多相关文章
- [MapReduce_3] MapReduce 程序运行流程解析
0. 说明 Word Count 程序运行流程解析 && MapReduce 程序运行流程解析 1. Word Count 程序运行流程解析 2. MapReduce 程序运行流程图
- Linux入门:运行级别解析
Linux入门:运行级别解析 一.查看当前运行级别 Ubuntu中,runlevel命令 可以查看当前运行级别: CentOS中,who -r 命令查看当前运行级别: www.2cto.com ...
- mapreduce运行机制
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt243 谈mapreduce运行机制,可以从很多不同的角度来描述,比如说从ma ...
- MapReduce运行原理
MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算.MapReduce采用”分而治之”的思想,把对大规模数据集的操作,分发给一个主节点管理下的各个分节点共同完成,然后通过整合各 ...
- (转)Apache和Nginx运行原理解析
Apache和Nginx运行原理解析 原文:https://www.server110.com/nginx/201402/6543.html Web服务器 Web服务器也称为WWW(WORLD WID ...
- View Animation 运行原理解析
Android 平台目前提供了两大类动画,在 Android 3.0 之前,一大类是 View Animation,包括 Tween animation(补间动画),Frame animation(帧 ...
- Mapreduce运行过程分析(基于Hadoop2.4)——(一)
1 概述 该瞅瞅MapReduce的内部执行原理了,曾经仅仅知道个皮毛,再不搞搞,不然怎么死的都不晓得.下文会以2.4版本号中的WordCount这个经典样例作为分析的切入点.一步步来看里面究竟是个什 ...
- Mapreduce运行过程分析(基于Hadoop2.4)——(二)
4.3 Map类 创建Map类和map函数.map函数是org.apache.hadoop.mapreduce.Mapper类中的定义的,当处理每一个键值对的时候,都要调用一次map方法,用户须 ...
- 一文读懂MapReduce 附流量解析实例
1.MapReduce是什么 Hadoop MapReduce是一个软件框架,基于该框架能够容易地编写应用程序,这些应用程序能够运行在由上千个商用机器组成的大集群上,并以一种可靠的,具有容错能力的方式 ...
随机推荐
- Python 爬虫从入门到进阶之路(十一)
之前的文章我们介绍了一下 Xpath 模块,接下来我们就利用 Xpath 模块爬取<糗事百科>的糗事. 之前我们已经利用 re 模块爬取过一次糗百,我们只需要在其基础上做一些修改就可以了, ...
- 2019.ccpc女生赛-wfinal总结
2019ccpc女生赛离它结束有四天了,在这个期间我想了很多,想了想还是决定写这个总结.作为这个队伍唯一的一名大一队员,我很庆幸,能跟着两个学姐一起打比赛,计爱玲师姐,即将工作,张莹俐学姐.这估计都是 ...
- [乐意黎原创]Centos 7里apache(httpd)自启动
最近,Aerchi在折腾 ECS服务器 (Centos 7),每次重启后都要手动开启apache服务,好繁琐. 仔细研究了下:Apache 的服务第一.启动.终止.重启systemctl start ...
- Vue的生命周期函数
详解Vue Lifecycle 先来看看vue官网对vue生命周期的介绍 Vue实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom.渲染→更新→渲染.销毁等一系列过程,我们称 ...
- 如何将 qsys 子模块设置为参数可调的方式给另外的qsys 调用
Intel FPGA Quartus 软件中的 Qsys工具 也就是 Platform Designer 系统集成工具,可以 图形化界面操作 使用系统自带ip,自定义ip 系统自动生成 ip 间的连接 ...
- 《深入浅出RxJS》读书笔记
rxjs的引入 // 如果以这种方式导入rxjs,那么整个库都会导入,我们一般不可能在项目中运用到rxjs的所有功能 const Rx = require('rxjs'); 解决这个问题,可以使用深链 ...
- Wannafly挑战赛1:Treepath(DFS统计)
题目链接 题意 给出一棵树,问长度为偶数的路径数有多少. 思路 记录路径长度为奇数的数目和为偶数的数目,然后 n * (n-1) / 2 求和即可. #include <bits/stdc++. ...
- scrapy实战8关于数据异步写入mysql:
环境:python3 爬取网址:腾讯社招(http://hr.tencent.com/position.php?keywords=&tid=0&start=0#a)总共2202条数据 ...
- scrapy实战3利用fiddler对手机app进行抓包爬虫图片下载(重写ImagesPipeline):
关于fiddler的使用方法参考(http://jingyan.baidu.com/article/03b2f78c7b6bb05ea237aed2.html) 本案例爬取斗鱼 app 先利用fidd ...
- django基础知识之ORM简介:
ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射”的简称 ...