MapReduce的原理分析

1.概述

MapReduce的思想核心是“分而治之,先分再合”,适用于大量复杂任务处理场景(大规模数据处理场景)。
MapReduce分两个阶段:

  • map阶段(分):如果任何可以拆分并且没有依赖,那么就把复杂的任务拆分成小任务,拆分成小任务之后,可以并行计算,提高处理效率。
  • reduce阶段(合):把map阶段的各个局部结果进行全局汇总,得到最终的结果

生活中的MapReduce案例:统计图书馆的书籍总数

“Map”:你数1号书架,我数2号书架。我们人越多,数书就更快。

“Reduce”:我们到一起,把所有人的统计数加在一起。

2.MapReduce架构

和HDFS一样,MapReduce也是采用Master/Slave的架构,其架构图如下所示 :
在这里插入图片描述

  • 客户端(Client)

    每一个job都会在用户通过Client类将应用程序以及配置参数 Configuration 打包成 JAR 文件存储在HDFS,并把路径提交到 JobTracker 的 master 服务,然后由 master 创建每一个 Task (即MapTask和 ReduceTask) 将他们分发到各个 TaskTracker 服务中去执行。

  • JobTracker

    JobTracker 负责资源监控和作业调度。JobTracker 监控所有TaskTracker 与 job 的健康状况,一旦发现失败,就将相应的任务转移到其他节点;同时,JobTracker 会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可以根据自己的需要设计相应的调度器。

  • TaskTracker

    TaskTracker 会周期性地通过Heartbeat 将本节点上资源的使用情况和任务的运行进度汇报给JobTracker,同时接收JobTracker 发送过来的命令并执行相应的操作(如启动新任务、杀死任务等)。TaskTracker 使用"slot"等量划分本节点上的资源量。"slot"代表计算资源(CPU、内存等)。一个Task 获取到一个slot 后才有机会运行,而Hadoop 调度器的作用就是将各个TaskTracker 上的空闲slot分配给Task 使用。slot分为Map slot 和Reduce slot 两种,分别供Map Task 和Reduce Task 使用。TaskTracker 通过slot 数目(可配置参数)限定Task 的并发度。

  • Task

    Task 分为Map Task 和Reduce Task 两种,均由TaskTracker 启动。HDFS 以固定大小的block 为基本单位存储数据,而对于MapReduce 而言,其处理单位是split。split 是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。但需要注意的是,split 的多少决定了Map Task 的数目,因为每个split 只会交给一个Map Task 处理。Split 和 Block的关系如下图所示 :
    在这里插入图片描述

3.MapReduce运行流程

一个mapreduce作业的执行流程是:作业提交->作业初始化->任务分配->任务执行->更新任务执行进度和状态->作业完成。
在这里插入图片描述

  • 1、提交作业

    • JobClient使用runjob方法创建一个JobClient实例,调用submitJob()方法进行作业的提交 。
  • 2、作业初始化

    • 当JobTracker收到Job提交的请求后,将Job保存在一个内部队列,并让Job Scheduler(作业调度器)处理并初始化。
    • 初始化涉及到创建一个封装了其tasks的job对象,并保持对task的状态和进度的跟踪(步骤5)。
    • 当创建要运行的一系列task对象后,Job Scheduler首先开始从文件系统中获取由JobClient计算的input splits(步骤6),然后再为每个split创建map task。
  • 3、任务分配

    • TaskTracker 和 JobTracker之间的通信和任务分配是通过心跳机制完成的。
    • TaskTracker作为一个单独的 JVM,它执行一个简单的循环,主要实现每隔一段时间向JobTracker发送心跳,告诉JobTracker此TaskTracker是否存活,是否准备执行新的任务。如果有待分配的任务,它就会为TaskTracker分配一个任务。
  • 4、任务的执行

    • TaskTracker申请到新的任务之后,就要在本地运行了。首先将任务本地化(包括运行任务所需的数据、配置信息、代码等),即从HDFS复制到本地,调用localizeJob()完成的。
    • 对于使用Streaming和Pipes创建Map或者Reduce程序的任务,Java会把key/value传递给外部进程,然后通过用户自定义的Map或者Reduce进行处理,然后把key/value传回到java中。其中就好像是TaskTracker的子进程在处理Map和Reduce代码一样。
  • 5、更新任务的执行进度和状态

    • 任务的进度和状态是通过heartbeat(心跳机制)来更新和维护的。
    • 对于Map Task,进度就是已处理数据和所有输入数据的比例。
    • 对于Reduce Task,情况就有点复杂,包括3部分,拷贝中间结果文件、排序、reduce调用,每部分占1/3。
  • 6、作业完成

    • 当 Job 完成后,JobTracker会收一个Job Complete的通知,并将当前的Job状态更新为successful。同时JobClient也会轮询获知提交的Job已经完成,将信息显示给用户。最后,JobTracker会清理和回收该Job的相关资源,并通知TaskTracker进行相同的操作(比如删除中间结果文件)

4.MapReduce处理过程分析

以单词计数为例,分析MR的整个计算过程
在这里插入图片描述

Q1 在MapReduce任务中,需要启动多少个MapTask任务去处理数据?

例如:/wordcount/input 1.txt 200M 2.txt 100M,FileInputFormat会进行逻辑切片。逐个遍历待处理目录针对待处理目录下的文件以及切片大小对文件形成规划。

split size=block size=128M 1个切片对应一个maptask

split-1 1.txt --> 0- 128M

split-2 1.txt --> 128- 200M

split-3 2.txt --> 0- 100M

Q2:数据何时写入缓冲区?

context.write(k2,v2)往外写数据,数据写入到磁盘里(disk),此时要考虑性能问题。如果读取一行数据,就调用map方法,就写入一次;如果有很多行(假设100行),程序就会执行很多次(100次),对应很多次的IO操作(100次)。此时就需要内存缓冲区(3个byte数组)称为环形缓冲区。默认缓冲区的大小为100M,当内存缓冲区的大小为80M时,就开始向磁盘写入数据;内存写到磁盘称为spill(溢出/溢写)。假设文件大小不足128M,至少会发生一次溢出,且在发生溢出行为时,会发生排序(字典序),溢出的次数=文件个数。

4.1 Mapper任务执行过程详解

  • 1、输入目录下的文件按照一定的标准逐个逻辑切片,形成规划;默认:split size = block size(默认128M);每一个切片由一个MapTask处理。
  • 2、默认读取数据组件TextInputFormat对切片中的数据(每一行文本内容)按照一定规则解析成一个<k,v>对。k:光标起始偏移量,v:此行内容。
  • 3、每一行内容解析出的每一个<k,v>对调用一次map方法,每次调用就会输出零个或多个键值对。(多少行调用多少次map方法)数据在缓冲。
  • 4、按照一定的规则对阶段3的键值对进行分区,默认只有一个区。当 reducetask=2 时,就会涉及数据分区;决定map输出的kv去到哪一个reducetask。分区的数量=reducetask的个数(正常情况) 异常情况:分区个数多 直接报错 非法分区 分区个数少 产生空文件。
  • 5、对每个分区中的键值对进行排序(溢写的同时–k的字典序);对溢出的临时文件合并为最终局部结果文件(分区且排序的文件)。
  • 6、数据局部聚合处理(combiner处理),键值相等的键值对会调用一次reduce方法。(本阶段默认是没有的)。

4.2 Reducer任务执行过程详解

  • 1、Reducer任务会主动从Mapper任务复制其输出的键值对。(开启线程(fetcher)主动拉取Map阶段输出的键值对)
  • 2、 1.**合并(merge)**复制到Reducer本地数据;2.排序(sort):对合并后的数据进行排序;3.分组(grouping) 对合并后的数进行分组(k,Iterable([1,1,1]))。
  • 3、键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对,将键值对写入到HDFS中。

5.MapTask工作机制

Map阶段流程大体如下图所示 :
在这里插入图片描述

1).input File通过split被逻辑切分为多个split文件,通过Record按行读取内容给map(用户自己实现的)进行处理。

2).数据被map处理结束之后交给OutputCollector收集器,对其结果key进行分区(默认使用hash分区)。

3).写入buffer,每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘。

4).当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。

详细步骤:

1. 读取数据组件InputFormat(默认TextInputFormat)会通过getSplits方法对输入目录中文件进行逻辑切片规划得到splits,有多少个split就对应启动多少个MapTask。split与block的对应关系默认是一对一。

2. 将输入文件切分为splits之后,由RecordReader对象(默认LineRecordReader)进行读取,以\n作为分隔符,读取一行数据,返回<key,value>。key:每行首字符偏移值,value:此行文本内容

3.读取split返回<key,value>,进入用户自己继承的Mapper类中,执行用户重写的map函数。RecordReader每读取一行内容就调用一次map方法。

4. map执行完之后,将map的每条结果通过context.write进行collect数据收集。在collect中,会先对其进行分区处理,默认使用HashPartitioner。

MapReduce提供Partitioner接口,它的作用就是根据key或value及reduce的数量来决定当前的这对输出数据最终应该交由哪个reduce task处理。默认为:key.hash % reduce task数量。默认的取模方式只是为了平均reduce的处理能力,如果用户自己对Partitioner有需求,可以订制并设置到job.setPartitionerClass上。

5.将数据写入内存,内存中这片区域叫做环形缓冲区,缓冲区的作用是批量收集map结果,减少磁盘IO的影响。我们的key/value对以及Partition的结果都会被写入缓冲区。当然写入之前,key与value值都会被序列化成字节数组。

注:环形缓冲区其实是一个数组,数组中存放着key、value的序列化数据和key、value的元数据信息,包括partition、key的起始位置、value的起始位置以及value的长度。环形结构是一个抽象概念。

缓冲区是有大小限制,默认是100MB。当map task的输出结果很多时,就可能会撑爆内存,所以需要在一定条件下将缓冲区中的数据临时写入磁盘,然后重新利用这块缓冲区。这个从内存往磁盘写数据的过程被称为Spill,中文可译为溢写。这个溢写是由单独线程来完成,不影响往缓冲区写map结果的线程。溢写线程启动时不应该阻止map的结果输出,所以整个缓冲区有个溢写的比例spill.percent。这个比例默认是0.8,也就是当缓冲区的数据已经达到阈值(buffer size * spill percent = 100MB * 0.8 = 80MB),溢写线程启动,锁定这80MB的内存,执行溢写过程。Map task的输出结果还可以往剩下的20MB内存中写,互不影响。

6.当溢写线程启动后,需要对这80MB空间内的key做排序(Sort)。排序是MapReduce模型默认的行为,这里的排序也是对序列化的字节做的排序

如果job设置过Combiner(局部聚合),那么现在就是使用Combiner的时候了。将有相同key的key/value对的value加起来,减少溢写到磁盘的数据量。Combiner会优化MapReduce的中间结果,所以它在整个模型中会多次使用。

那哪些场景才能使用Combiner呢?从这里分析,Combiner的输出是Reducer的输入,Combiner绝不能改变最终的计算结果。Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。Combiner的使用一定得慎重,如果用好,它对job执行效率有帮助,反之会影响reduce的最终结果。

7. 每次溢写会在磁盘上生成一个临时文件(写之前判断是否有combiner),如果map的输出结果真的很大,有多次这样的溢写发生,磁盘上相应的就会有多个临时文件存在。当整个数据处理结束之后开始对磁盘中的临时文件进行merge合并,因为最终的文件只有一个,写入磁盘,并且为这个文件提供了一个索引文件,以记录每个reduce对应数据的偏移量。

6.Shuffle机制

map阶段处理的数据如何传递给reduce阶段,是MapReduce框架中最关键的一个流程,这个流程就叫shuffle

shuffle: 洗牌、发牌——(核心机制:数据分区,排序,合并)。

在这里插入图片描述

shuffle是Mapreduce的核心,它分布在Mapreduce的map阶段和reduce阶段,描述了两个阶段之间数据处理的特性。

一般把从Map产生输出开始到Reduce取得数据作为输入之前的过程称作shuffle

shuffle过程:

Map阶段:

  • Collect阶段:将MapTask的结果输出到默认大小为100M的环形缓冲区,保存的是key/value,Partition分区信息等。
  • Spill阶段:当内存中的数据量达到一定的阀值(spill percent=0.8)的时候,就会将数据写入本地磁盘; 数据写入磁盘之前需要对数据进行一次排序的操作; 如果配置了combiner(默认是没有的),maptask的结果进行局部聚合。
  • Merge阶段:把所有溢出的临时文件进行一次合并操作,以确保一个MapTask最终只产生一个中间数据文件。

Reduce阶段:

  • Copy阶段 :ReduceTask启动Fetcher线程到已经完成MapTask的节点上复制一份属于自己的数据 数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上。
  • Merge阶段 :在ReduceTask远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。
  • Sort阶段 :在对数据进行合并的同时,会进行排序操作;MapTask阶段已经对数据进行了局部的排序,ReduceTask只需保证Copy的数据的最终整体有效性即可。

shuffle是Mapreduce的诟病所在;原因是在shuffle过程中涉及到了大量的内存到磁盘 磁盘到内存 内存再到磁盘的过程,执行效率大大降低。

当涉及多个mr程序之间的串联执行的时候,shuffle的弊端 就会被无限放大,故mr程序不是合做迭代计算。

Shuffle中的缓冲区大小会影响到mapreduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快。

7.ReduceTask工作机制

Reduce阶段流程大体如下图所示 :
在这里插入图片描述
Reduce大致分为copy、sort、reduce三个阶段,重点在前两个阶段。copy阶段包含一个eventFetcher来获取已完成的map列表,由Fetcher线程去copy数据,在此过程中会启动两个merge线程,分别为inMemoryMerger和onDiskMerger,分别将内存中的数据merge到磁盘和将磁盘中的数据进行merge。待数据copy完成之后,copy阶段就完成了,开始进行sort阶段,sort阶段主要是执行finalMerge操作,纯粹的sort阶段,完成之后就是reduce阶段,调用用户定义的reduce函数进行处理。

详细步骤:

1.Copy阶段,简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求maptask获取属于自己的文件。

2. Merge阶段。 这里的merge如map端的merge动作,只是数组中存放的是不同map端copy来的数值。Copy过来的数据会先放入内存缓冲区中,这里的缓冲区大小要比map端的更为灵活。

merge有三种形式:内存到内存;内存到磁盘;磁盘到磁盘。默认情况下第一种形式不启用

当内存中的数据量到达一定阈值,就启动内存到磁盘的merge。与map 端类似,这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。第二种merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的文件。

3.把分散的数据合并成一个大的数据后,还会再对合并后的数据排序。

4. 对排序后的键值对调用reduce方法,键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到HDFS文件中。

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

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

相关文章

Ubuntu 安装 KVM 虚拟化

1. Ubuntu 安装 KVM 虚拟化 KVM 是 Linux 内核中一个基于 hypervisor 的虚拟化模块&#xff0c;它允许用户在 Linux 操作系统上创建和管理虚拟机。 如果机器的CPU不支持硬件虚拟化扩展&#xff0c;是无法使用KVM(基于内核的虚拟机)直接创建和运行虚拟机的。此时最多只能使用…

SpringBoot3整合Elasticsearch8.x之全面保姆级教程

整合ES 环境准备 安装配置ES&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136724528安装配置Kibana&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136727707新建项目&#xff1a;新建名为web的SpringBoot3项目 elasticsearch-java 公…

uploads-labs靶场(1-10关)

一、搭建环境: 下载upload-labs源代码 下载链接&#xff1a;https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master 将压缩包解压后的文件名改为upload-labs&#xff0c;然后放入phpstudy\www目录下 二、关卡通关: 1、pass-01&#xff08;前端绕过&#xf…

B. Array Fix

思路&#xff1a;我们倒着看&#xff0c;首先判断以下当前元素有没有被操作过&#xff0c;被操作过的话&#xff0c;那么需要改为操作后的数&#xff0c;然后跟当前数的前一个数进行比较&#xff0c;如果a[i] < a[i - 1]的话&#xff0c;那么需要将a[i - 1]拆分&#xff0c;…

【SpringBoot】头条新闻项目实现CRUD登录注册

文章目录 一、头条案例介绍二、技术栈介绍三、前端搭建四、基于SpringBoot搭建项目基础架构4.1 数据库脚本执行4.2 搭建SprintBoot工程4.2.1 导入依赖:4.2.2 编写配置4.2.3 工具类准备 4.3 MybatisX逆向工程 五、后台功能开发5.1 用户模块开发5.1.1 jwt 和 token 介绍5.1.2 jwt…

huawei services HK华为云服务

huaweiserviceshk是一种云计算服务&#xff0c;为华为云服务用户提供了多种服务&#xff0c;包括云服务器、数据库、存储、网络等&#xff0c;用户可以根据自己的需求选择不同的服务并支付相应的费用 如何付费呢&#xff0c;这里可以使用441112&#xff0c;点击获取 卡片信息在…

springboot+poi-tl根据模板导出word(含动态表格和图片),并将导出的文档压缩zip导出

springbootpoi-tl根据模板导出word&#xff08;含动态表格和图片&#xff09; 官网&#xff1a;http://deepoove.com/poi-tl/ 参考网站&#xff1a;https://blog.csdn.net/M625387195/article/details/124855854 pom导入的maven依赖 <dependency><groupId>com.dee…

基于openCV实现的单目相机行人和减速带检测

概述 在计算机视觉项目中&#xff0c;相机标定是一项至关重要的任务&#xff0c;因为它可以校正相机内部参数&#xff0c;消除因镜头畸变等因素导致的图像失真&#xff0c;从而提高后续图像处理和分析的精度。在这个项目中&#xff0c;相机标定的核心功能集成在名为calibratio…

还原wps纯粹的编辑功能

1.关闭稻壳模板&#xff1a; 1.1. 启动wps(注意不要乱击稻壳模板&#xff0c;点了就找不到右键菜单了) 1.2. 在稻壳模板选项卡右击&#xff1a;选不再默认展示 2.关闭托盘中wps云盘图标&#xff1a;右击云盘图标/同步与设置&#xff1a; 2.1.关闭云文档同步 2.2.窗口选桌面应用…

Vue2+ElementUI表单、Form组件的封装

Vue2ElementUI表单、Form组件的封装 &#xff1a;引言 在 Vue2 项目中&#xff0c;ElementUI 的 el-form 组件是常用的表单组件。它提供了丰富的功能和样式&#xff0c;可以满足各种需求。但是&#xff0c;在实际开发中&#xff0c;我们经常会遇到一些重复性的需求&#xff0c…

16.WEB渗透测试--Kali Linux(四)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;15.WEB渗透测试--Kali Linux&#xff08;三&#xff09;-CSDN博客 1.crunch简介与使用 C…

分布式CAP理论

CAP理论&#xff1a;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容错性&#xff08;Partition tolerance&#xff09;。是Eric Brewer在2000年提出的&#xff0c;用于描述分布式系统基本性质的定理。这三个性质在分布式系统…

FPGA静态时序分析与约束(一)、理解亚稳态

系列文章目录 FPGA静态时序分析与约束&#xff08;二&#xff09;、时序分析 FPGA静态时序分析与约束&#xff08;三&#xff09;、读懂vivado时序报告 文章目录 系列文章目录前言一、概述一、何为亚稳态&#xff1f;二、图解亚稳态三、什么时候亚稳态会导致系统失效&#xff…

k8s部署hadoop

&#xff08;作者&#xff1a;陈玓玏&#xff09; 配置和模板参考helm仓库&#xff1a;https://artifacthub.io/packages/helm/apache-hadoop-helm/hadoop 先通过以下命令生成yaml文件&#xff1a; helm template hadoop pfisterer-hadoop/hadoop > hadoop.yaml用kube…

Unity PS5开发 天坑篇 之 申请开发者与硬件部署01

腾了好几天终于把PS5开发机调试部署成功, 希望能帮到国内的开发者, 主机游戏PlayStation/Nintendo Switch都是比较闭塞的&#xff0c;开发者账号是必须的。 开发环境有两个部分&#xff0c;一是DEV Kit 开发机, TEST Kit测试机两部分组成&#xff0c;二是Unity的支持库(安装后…

最新开源解密版TwoNav网址导航系统源码

源码简介 2024最新开源解密版TwoNav网址导航系统源码去授权破解版 内置二十多套主题模板。 已去授权&#xff0c;最新开源解密版。TwoNav 是一款开源的书签&#xff08;导航&#xff09;管理程序&#xff0c;使用PHP SQLite 3开发&#xff0c;界面简洁&#xff0c;安装简单&…

FFmepg--音频编码流程--pcm编码为aac

文章目录 基本概念流程apicode(核心部分) 基本概念 从本地⽂件读取PCM数据进⾏AAC格式编码&#xff0c;然后将编码后的AAC数据存储到本地⽂件。 PCM样本格式&#xff1a;未经压缩的⾳频采样数据裸流 参数&#xff1a; Sample Rate : 采样频率Sample Size : 量化位数Number o…

Matlab进阶绘图第45期—蝴蝶气泡图

蝴蝶气泡图是一种特殊的柱泡图/气泡柱状图。 蝴蝶图一般由左右两个水平柱状图组合而成&#xff0c;其形如蝴蝶展翅&#xff0c;可以很直观地展示两种数据直接的差异。 而蝴蝶气泡图则是在两个水平柱状图每根柱子外侧额外添加大小不同的气泡&#xff0c;用于表示另外一个数据变…

使用IDEA2023创建传统的JavaWeb项目并运行与调试

日期:2024-0312 作者:dusuanyun 文档环境说明: OS:Deepin 20.9(Linux) JDK: OpenJDK21 Tomcat:10.1.19 IDEA: 2023.3.4 (Ultimate Edition) 本文档默认已经安装JDK及环境变量的配置。 关键词…

单片机设计-超声波视力保护仪的设计与实现

项目介绍 技术&#xff1a;C语言、单片机等 本设计利用超声波技术检测眼睛与书本的距离&#xff0c;调整看书位置&#xff0c;通过光敏检测判断环境光线强度是否适合阅读&#xff0c;并通过定时器设定阅读时长&#xff0c;以此解决人们由于看书姿势的错误&#xff0c;阅读环境…