MapReduce的工作原理

一、MapReduce模型框架

       MapReduce是一个用于大规模数据处理的分布式计算模型,最初由Google工程师设计并实现的,Google已经将完整的MapReduce论文公开发布了。其中的定义是,MapReduce是一个编程模型,是一个用于处理和生成大规模数据集的相关的实现。用户定义一个map函数来处理一个Key-Value对以生成一批中间的Key-Value对,再定义一个reduce函数将所有这些中间的有相同Key的Value合并起来。很多现实世界中的任务都可用这个模型来表达。

1、MapReduce模型


源数据                                 中间数据                  结果数据

MapReduce模型如上图所示,Hadoop MapReduce模型主要有Mapper和Reducer两个抽象类。Mapper端主要负责对数据的分析处理,最终转化为Key-Value的数据结构;Reducer端主要是获取Mapper出来的结果,对结果进行统计。


2、MapReduce框架


整个过程如上图所示,包含4个独立的实体,如下所示:

  • client:提交MapReduce作业,比如,写的MR程序,还有CLI执行的命令等。
  • jobtracker:协调作业的运行,就是一个管理者。
  • tasktracker:运行作业划分后的任务,就是一个执行者。
  • hdfs:用来在集群间共享存储的一种抽象的文件系统。
说明:
其实,还有namenode就是一个元数据仓库,就像windows中的注册表一样。secondarynamenode可以看成namenode的备份。datanode可以看成是用来存储作业划分后的任务。在DRCP中,master是namenode,secondarynamenode,jobtracker,其它的3台slaver都是tasktracker,datanode,且tasktracker都需要运行在HDFS的datanode上面。
MapReduce框架中组成部分及它们之间的关系,如下所示:
  • Mapper和Reducer
运行在Hadoop上的MapReduce应用程序最基本的组成部分包括:一是Mapper抽象类,一是Reducer抽象类,一是创建JobConf的执行程序。
  • JobTracker
JobTracker是一个master服务,软件启动之后JobTracker接收Job,负责调度Job的每一个子任务Task运行于TaskTracker上,并且监控它们的运行,如果发现有失败的Task就重新运行它,一般情况下应该把JobTracker部署在单独的机器上。
  • TaskTracker
TaskTracker是运行在多个节点上的slaver服务。TaskTracker主动与JobTracker通信(与DataNode和NameNode相似,通过心跳来实现)接收作业,并负责直接执行每一个任务。
  • JobClient
每一个Job都会在用户端通过JobClient类将应用程序以及配置参数Configuration打包成JAR文件存储在HDFS中,并把路径提交到JobTracker的master服务,然后由master创建每一个Task(即MapTask和ReduceTask)将它们分发到各个TaskTracker服务中去执行。
  • JobInProgress
JobClient提交Job后,JobTracker会创建一个JobInProgress来跟踪和调度这个Job,并把它添加到Job队列之中。JobInProgress会根据提交的任务JAR中定义的输入数据集(已分解成FileSplit)创建对应的一批TaskInProgress用于监控和调度MapTask,同时创建指定书目的TaskInProgress用于监控和调度ReduceTask,默认为1个ReduceTask。
  • TaskInProgress
JobTracker启动任务时通过每一个TaskInProgress来运行Task,这时会把Task对象(即MapTask和ReduceTask)序列化写入相应的TaskTracker服务中,TaskTracker收到后会创建对应的TaskInProgress(此TaskInProgress实现非JobTracker中使用的TaskInProgress,作用类似)用于监控和调度该Task。启动具体的Task进程通过TaskInProgress管理,通过TaskRunner对象来运行。TaskRunner会自动装载任务JAR文件并设置好环境变量后,启动一个独立的Java Child进程来执行Task,即MapTask或者ReduceTask,但它们不一定运行在同一个TaskTracker中。
  • MapTask和ReduceTask
一个完整的Job会自动依次执行Mapper、Combiner(在JobConf指定Combiner时执行)和Reducer,其中Mapper和Combiner是由MapTask调用执行,Reduce则由ReduceTask调用,Combiner实际也是Reducer接口类的实现。Mapper会根据Job JAR中定义的输入数据集<key1, value1>对读入,处理完成生成临时的<key2, value2>对,如果定义了Combiner,MapTask会在Mapper完成调用该Combiner将相同Key的值做合并处理,以减少输出结果集。MapTask的任务全部完成后,交给ReduceTask进程调用Reducer处理,生成最终结果<Key3, value3>对。

二、MapReduce工作原理


1、作业的提交
JobClient的submitJob()方法实现的作业提交过程,如下所示:
  • 通过JobTracker的getNewJobId()方法,向jobtracker请求一个新的作业ID。参见步骤2。
  • 检查作业的输出说明,也就是说要指定输出目录的路径,但是输出目录还不能存在(防止覆盖输出结果),如果不满足条件,就会将错误抛给MapReduce程序。
  • 检查作业的输入说明,也就是说如果输入路径不存在,作业也没法提交,如果不满足条件,就会将错误抛给MapReduce程序。
  • 将作业运行所需的资源,比如作业JAR文件、配置文件等复制到HDFS中。参见步骤3。
  • 通过JobTracker的submitJob()方法,告诉jobtracker作业准备执行。参见步骤4。
2、作业的初始化
  • JobTracker接收到对其submitJob()方法调用之后,就会把此调用放入一个内部队列当中,交由作业调度器进行调度。(说明:Hadoop作业的调度器常见的有3个:先进先出调度器;容量调度器;公平调度器。Hadoop作业调度器采用的是插件机制,即作业调度器是动态加载的、可插拔的,同时第三方可以开发自己的作业调度器,参考资料”大规模分布式系统架构与设计实战”)。参见步骤5。
  • 初始化包括创建一个表示正在运行作业的对象——封装任务的记录信息,以便跟踪任务的状态和进程。参见步骤5。
  • 接下来要创建运行任务列表,作业调度器首先从共享文件系统中获取JobClient已计算好的输入分片信息,然后为每个分片创建一个map任务(也就是说mapper的个数与分片的数目相同)。参见步骤6。(创建reduce任务的数量由JobConf的mapred.reduce.task属性决定,它是用setNumReduceTasks()方法来设置的,然后调度器创建相应数量的要运行的reduce任务,默认情况只有一个reducer)
3、任务的分配
  • tasktracker本身运行一个简单的循环来定期发送”心跳(heartbeat)”给jobtracker。什么是心跳呢?就是tasktracker告诉jobtracker它是否还活着,同时心跳也充当两者之间的消息通信,比如tasktracker会指明它是否已经做好准备来运行新的任务了,如果是,管理者jobtracker就会给执行者tasktracker分配一个任务。参见步骤7。
  • 当然,在管理者jobtracker为执行者tasktracker选择任务之前,jobtracker必须先选定任务所在的作业。一旦选择好作业,jobtracker就可以给tasktracker选定一个任务。如何选择一个作业呢?当然是Hadoop作业的调度器了,它就像是Hadoop的中枢神经系统一样,默认的方法是简单维护一个作业优先级列表。(对于调度算法的更深理解可以学习操作系统的作业调度算法,进程调度算法,比如先来先服务(FCFS)调度算法,短作业优先(SJF)调度算法,优先级调度算法,高响应比优先调度算法,时间片轮转调度算法,多级反馈队列调度算法等。如果从更高的角度来看调度算法,其实是一种控制和决策的策略选择。)
4、任务的执行
  • 作业选择好了,任务也选择好了,接下来要做的事情就是任务的运行了。首先,从HDFS中把作业的JAR文件复制到tasktracker所在的文件系统,同时,tasktracker将应用程序所需要的全部文件从分布式缓存复制到本地磁盘,也就是从HDFS文件系统复制到ext4等文件系统之中。参见步骤8。
  • tasktracker为任务新建一个本地工作目录,并把JAR文件中的内容解压到这个文件夹中,新建一个TaskRunner实例来运行该任务。
  • TaskRunner启动一个新的JVM(参见步骤9)来运行每个任务(参见步骤10),以便用户定义的map和reduce函数的任何缺陷都不会影响TaskTracker守护进程(比如导致它崩溃或者挂起)。需要说明一点的是,对于map和reduce任务,tasktracker有固定数量的任务槽,准确数量由tasktracker核的数量和内存大小来决定,比如一个tasktracker可能同时运行两个map任务和reduce任务。map任务和reduce任务中关于数据本地化部分不再讲解,因为DRCP没有用到,只要理解本地数据级别就可以了,比如node-local,rack-local,off-switch。
  • 子进程通过umbilical接口与父进程进行通信,任务的子进程每隔几秒便告诉父进程它的进度,直到任务完成。
5、进度和状态的更新

  • MapReduce是Hadoop的一个离线计算框架,运行时间范围从数秒到数小时,因此,对于我们而言直到作业进展是很重要的。
  • 一个作业和每个任务都有一个状态信息,包括作业或任务的运行状态(比如,运行状态,成功完成,失败状态)、Map和Reduce的进度、计数器值、状态消息和描述(可以由用户代码来设置)等。
  • 这些消息通过一定的时间间隔由Child JVM—>TaskTracker—>JobTracker汇聚。JobTracker将产生一个表明所有运行作业及其任务状态的全局视图。可以通过Web UI查看。同时JobClient通过每秒查询JobTracker来获得最新状态,输出到控制台上。
  • 现在可能会有一个疑问,这些状态信息在作业执行期间不断变化,它们是如何与客户端进行通信的呢?详细细节不在讲解,参考资料《Hadoop权威指南》。
6、作业的完成
  • 当jobtracker收到作业最后一个任务已完成的通知后,便把作业的状态设置为”成功”。然后,在JobClient查询状态时,便知道作业已成功完成,于是JobClient打印一条消息告知用户,最后从runJob()方法返回。
说明:
MapReduce容错,即作业失败情况不再讲解,参考资料《Hadoop权威指南》。

三、Shuffle阶段和Sort阶段

如果说以上是从物理实体的角度来讲解MapReduce的工作原理,那么以上便是从逻辑实体的角度来讲解MapReduce的工作原理,如下所示:
  1. 输入分片: 在进行map计算之前,mapreduce会根据输入文件计算输入分片,每个输入分片针对一个map任务,输入分片存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组,输入分片往往和hdfs的block关系很密切。假如我们设定hdfs块的大小是64MB,如果我们有三个输入文件,大小分别是3MB、65MB和127MB,那么mapreduce会把3MB文件分为一个输入分片,65MB则是两个输入分片,而127MB也是两个输入分片,就会有5个map任务将执行。
  2. map阶段: 就是编写好的map函数,而且一般map操作都是本地化操作,也就是在数据存储节点上进行。
  3. combiner阶段: combiner阶段是可以选择的,combiner本质也是一种reduce操作。Combiner是一个本地化的reduce操作,它是map运算的后续操作,主要是在map计算出中间文件后做一个简单的合并重复key值的操作,比如,我们对文件里的单词频率做统计,如果map计算时候碰到一个hadoop单词就会记录为1,这篇文章里hadoop可能会出现多次,那么map输出文件冗余就会很多,因此在reduce计算前对相同的key做一个合并操作,文件就会变小,这样就提高了宽带的传输效率。但是combiner操作是有风险的,使用它的原则是combiner的输入不会影响到reduce计算的最终结果,比如:如果计算只是求总数,最大值,最小值可以使用combiner,但是如果做平均值计算使用combiner,那么最终的reduce计算结果就会出错。
  4. shuffle阶段: 将map的输出作为reduce输入的过程就是shuffle。一般mapreduce计算的都是海量数据,map输出的时候不可能把所有文件都放到内存中进行操作,因此map写入磁盘的过程十分的复杂,更何况map输出的时候要对结果进行排序,内存开销是很大的。map在做输出的时候会在内存里开启一个环形内存缓冲区,这个缓冲区是专门用来输出的,默认大小是100MB,并且在配置文件里为这个缓冲区设定了一个阀值,默认是0.80(这个大小和阀值都是可以在配置文件里进行配置的),同时map还会为输出操作启动一个守护线程,如果缓冲区的内存达到了阀值的80%时候,这个守护线程就会把内容写到磁盘上,这个过程叫spill。另外的20%内存可以继续写入要写进磁盘的数据,写出磁盘和写入内存操作是互不干扰的,如果缓存区被填满了,那么map就会阻塞写入内存的操作,让写出磁盘操作完成后再继续执行写入内存操作。写出磁盘前会有个排序操作,这个是在写出磁盘操作的时候进行的,不是在写入内存的时候进行的,如果还定义了combiner函数,那么排序后还会执行combiner操作。每次spill操作也就是写出磁盘操作的时候就会写一个溢出文件,即在做map输出的时候有几次spill操作就会产生多少个溢出文件。这个过程里还会有一个partitioner操作,其实partitioner操作和map阶段的输入分片很像,一个partitioner对应一个reduce作业,如果mapreduce操作只有一个reduce操作,那么partitioner就只有一个。如果有多个reduce操作,那么partitioner对应的就会有多个。因此,可以把partitioner看作reduce的输入分片。到了reduce阶段就是合并map输出文件,partitioner会找到对应的map输出文件,然后进行复制操作,复制操作时reduce会开启几个复制线程,这些线程默认个数是5个(也可以在配置文件中更改复制线程的个数),这个复制过程和map写出磁盘的过程类似,也有阀值和内存大小,阀值一样可以在配置文件里配置,而内存大小是直接使用reduce的tasktracker的内存大小,复制的时候reduce还会进行排序操作和合并文件操作,这些操作完毕之后就会进行reduce计算。
  5. reduce阶段: 和map函数一样,是编写好的reduce函数,最终结果是存储在hdfs上的。

参考文献:

[1] MapReduce编程模型的要点: http://blog.sina.com.cn/s/blog_4a1f59bf0100tgqj.html

[2] Hadoop权威指南(第三版)

[3] Hadoop应用开发技术详解

[4] mapreduce中reducers个数设置: http://www.2cto.com/os/201312/263998.html

[5] 操作系统典型调度算法: http://see.xidian.edu.cn/cpp/html/2595.html

[6] MapReduce框架结构: http://www.cppblog.com/javenstudio/articles/43073.html

[7] MapReduce框架详解: http://www.cnblogs.com/sharpxiajun/p/3151395.html



转载于:https://www.cnblogs.com/cn-7876/p/7781040.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react实现多行文本超出加省略号

http://www.css88.com/archives/5206 overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; 根据该文章方法&#xff0c;放在react项目中发现并不能实现&#xff0c;仔细观察发现原来react解析出来的css样…

qq群 html,我的群组-普通群组.html

&#xfeff;我的群组&#xff0d;普通群组$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resou…

查看PLC IP 端口_西门子828D数控系统X130接口通讯怪异现象(X130手动设置的 IP)...

西门子828D数控系统&#xff0c;调试PLC过程中遇到网络通信怪异问题(不能直连非要加个路由器)&#xff0c;笔记本电脑的以太网网络直接连接显示网络电缆被拔出&#xff0c;如下图所示&#xff1a;奇怪&#xff0c;怎么出现这种情况了呢&#xff0c;因为我用这台电脑调试过别的P…

bzoj1263

贪心 n%31 分出一个4&#xff0c;其余用3&#xff0c;n%32&#xff0c;分出一个2&#xff0c;其余用3&#xff0c;然后高精度就行了 #include<bits/stdc.h> using namespace std; const int N 5005; struct BigInt {int len;int a[N];BigInt() { memset(a, 0, sizeof(a)…

c语言volatile_[技术]为什么单片机C语言编程时某一变量有时乱码

最近一个项目里面&#xff0c;在KEIL中用C语言在单片机里面定义了一个状态机全局变量&#xff0c;这个变量随时会改变&#xff0c;用于切换触摸屏的界面&#xff0c;可是程序运行中出现了一个问题&#xff0c;这个状态机号总是出现了被莫名奇妙改变的问题&#xff0c;导致触屏不…

微型计算机2017年9月上,2017年9月计算机一级考试WPS Office冲刺题

2017年9月计算机一级考试WPS Office冲刺题2017年下半年计算机一级考试将在9月份进行&#xff0c;为了方便考生备考计算机一级考试。下面是小编为大家带来的计算机一级考试WPS Office冲刺题&#xff0c;欢迎阅读。冲刺题一&#xff1a;1、PowerPoint 演示文稿和模板的扩展名是【…

11尺寸长宽 iphone_弱电工程LED显示屏尺寸规格及计算方法

前言&#xff1a;led屏幕在生活中&#xff0c;随处可见&#xff0c;显示屏、广播屏等等&#xff0c;但是led尺寸怎么计算的&#xff0c;你知道吗&#xff1f;今天我们一起了解一下led屏幕尺寸的计算方法。正文&#xff1a;一、点间距的计算1、各单元板常见型号及尺寸LED屏普遍是…

marquee标签的使用

<!DOCTYPE html> <html> <head><meta charset"utf-8" /><title>演示marquee</title><style type"text/css">*{padding: 0px;margin: 0px;}marquee{border: 1px solid purple;}img{width: 360px;height: auto;}&…

32位数据源中没有mysql_[SpringBoot实战]快速配置多数据源(整合MyBatis)

前言由于业务需求&#xff0c;需要同时在SpringBoot中配置两套数据源&#xff08;连接两个数据库&#xff09;&#xff0c;要求能做到service层在调用各数据库表的mapper时能够自动切换数据源&#xff0c;也就是mapper自动访问正确的数据库。本文内容&#xff1a;在SpringbootM…

考研计算机冷门学校,考研5个冷门的985院校 别随大流,这些几所也是很不错的...

导语&#xff1a;想必大家考研的目的有很多&#xff0c;最主要的就是想去更好的学校提升自己&#xff0c;大部分会肯定是会更倾向于985这类的院校&#xff0c;每年其实除了那些被“挤破头”的985院校&#xff0c;其实还有不少“低调”的985院校是非常值得报考的&#xff0c;下面…

名为 cursor_jinserted 的游标不存在_质量工程师必须了解的测量常识,你不知道怎么行...

01测量器具的分类测量器具是一种具有固定形态、用以复现或提供一个或多个已知量值的器具。按用途的不同量具可分为以下几类&#xff1a;1. 单值量具只能体现一个单一量值的量具。可用来校对和调整其它测量器具或作为标准量与被测量直接进行比较&#xff0c;如量块、角度量块等。…

bzoj4869

http://www.lydsy.com/JudgeOnline/problem.php?id4869 终于A了。。。参考了下dalao的代码。。。 拓展欧几里得定理&#xff0c;改了几次就不变了&#xff0c;但是用的时候要在快速幂里判是不是要用。 #include<bits/stdc.h> using namespace std; typedef long long ll…

一张图一个表——CSS选择器总结

CSS选择器总结&#xff1a; (这些表是一张图片^_^) 看底部 完整思维导图图片和表格的下载地址&#xff1a;https://download.csdn.net/download/denlnyyr/10597820 &#xff08;我不想选择要积分币下载的&#xff0c;但那里最低必须选择1个积分……&#xff09; 参考文献&…

native层 安卓_安卓逆向——拼xx协议java层分析

制丨阿星整理丨阿星老铁们大家好&#xff0c;今天小编给大家带来很实用的技巧叫拼xx协议java层分析&#xff0c;有啥不足的地方望大家指点指点&#xff01;首先抓包 反编译这个时间段我们方法剖析一下找到onclick 看他的走向找到方法的地方都是在进行写入 所以我们直接分析结果…

Java集合框架图

转载于:https://www.cnblogs.com/areyouready/p/6835279.html

JavaScript学习第一天(一)

JavaScript介绍 JavaScript一种直译式脚本语言&#xff0c;是一种动态类型、弱类型、基于原型的语言&#xff0c;内置支持类型。它的解释器被称为JavaScript引擎&#xff0c;为浏览器的一部分&#xff0c;广泛用于客户端的脚本语言&#xff0c;最早是在HTML&#xff08;标准通用…

折半查找的思想及源码_常用排序与查找算法

1 选择排序选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是&#xff1a;第一次从待排序的数据元素中选出最小(或最大)的一个元素&#xff0c;存放在序列的起始位置&#xff0c;然后再从剩余的未排序元素中寻找到最小(大)元素&#xff0c;然后放到已排序的序…

滚动视差?CSS 不在话下

何为滚动视差 视差滚动&#xff08;Parallax Scrolling&#xff09;是指让多层背景以不同的速度移动&#xff0c;形成立体的运动效果&#xff0c;带来非常出色的视觉体验。 作为网页设计的热点趋势&#xff0c;越来越多的网站应用了这项技术。 通常而言&#xff0c;滚动视差在…

番石榴的弦类

在“ 检查Java中的空&#xff0c;空或仅空白字符串”一文中 &#xff0c;我演示了Java生态系统&#xff08;标准Java&#xff0c; Guava &#xff0c; Apache Commons Lang和Groovy &#xff09;中用于检查字符串是否为空&#xff0c;空或空白的常见方法。仅类似于C&#xff03…

用python做数据分析流程图_使用Pyecharts进行高级数据可视化

欢迎使用Markdown编辑器经管之家&#xff1a;Do the best economic and management education&#xff01;你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语…