Hadoop大数据技术原理与应用-第四章MapReduce分布式计算框架

4.1 MapReduce 概述

4.1.1 MapReduce 核心思想

MapReduce的核心思想是“分而治之”。所谓“分而治之”就是把一个复杂的问题,按照一定的“分解"方法分为等价的规模较小的若干部分,然后逐个解决,分别找出各部分的结果,把各部分的结果组成整个问题的结果,这种思想来源于日常生活与工作时的经验,同样也完全适合技术领域。
MapReduce作为一种分布式计算模型,它主要用于解决海量数据的计算问题。使用MapReduce分析海量数据时,每个MapReduce程序被初始化为一个工作任务,每个工作任务可以分为MapReduce两个阶段,具体介绍如下。

  • Map阶段:负责将任务分解,即把复杂的任务分解成若干个“简单的任务”来并行处理,但前提是这些任务没有必然的依赖关系,可以单独执行任务。
  • Reduce阶段:负责将任务合并,即把Map阶段的结果进行全局汇总。
    在这里插入图片描述

4.1.2 MapReduce 编程模型

MapReduce编程模型借鉴了函数式程序设计语言的设计思想,其程序实现过程是通过map()和reduce()函数来完成的。从数据格式上来看,map()数接收的数据格式是键值对,产生的输出结果也是键值对形式,代duce()孓数会将map0数输出的键值对作为输人,把相同key值的value进行汇总,输出新的键值对。
在这里插入图片描述
对于图4一3描述的MapReduce简易数据流模型说明如下:

  1. 原始数据处理成**键值对<K1,V1>**形式。
  2. 将解析后的键值对<K1,V1>传给map()函数,map()函数会根据映射规则,将键值对<K1,V1>映射为一系列中间结果形式的键值对<K2,V2>
  3. 将中间形式的键值对<K2,V2>形成<K2,{V2,……}>形式传给 reduce()函数 处理,把具有相同key的value 合并 在一起,产生新的键值对<K3,V3>,此时的键值对 <K3,V3>就是最终输出的结果。
    这里需要说明的是,对于某些任务来说,可能不一定需要Reduce过程,也就是说,MapReduce的数据流模型可能
    只有Map过程
    ,由Map产生的数据直接被写人HDFS中。但是,对于大多数任务来说,都是需要Reduce过程的,并且可能由于任务繁重,需要设定多个Reduce,例如,下面是一个具有多个Map和Reduce的MapReduce模型,具体如图4一4
    在这里插入图片描述
    图4一4演示的是含有3个Map2个Reduce的MapReduce程序,其中,由Map产生的相关key的输出都会集中到Reduce中处理,而Reduce是最后的处理过程,其结果不会进行第二次汇总。

4.1.3 MapReduce 编程实例——词频统计

假设有文件4-1和文件4-2两个文本文件,这两个文本文件位于HDFS中。
文件4-1 text1.txt
Hello World
Hello Hadoop
Hello itcast
文件4-2 text2.txt
Hadoop MapReduce
MapReduce Spark
根据MapReduce编程模型,那么单词计数的实现过程,如图4一5所示。
在这里插入图片描述
在图4-5中,首先,MapReduce通过默认组件TextlnputFormat将待处理的数据文件(如text1.txt和text2.txt),把每一行的数据都转变为<key,value>键值对(其中,对应key为偏移量,value为这一行的文本内容);其次,调用map()方法,将单词进行切割并进行计数,输出键值对作为Reduce阶段的输人键值对;最后,调用reduce()方法将单词汇总、排序后,通过TextOutputFormat组件输出到结果文件中。

4.2 MapReduce 工作原理

4.2.1 MapReduce 工作过程

在这里插入图片描述
分片、格式化数据源
输人Map阶段的数据源,必须经过分片和格式化操作。其中:
- 分片操作:指的是将源文件划分为大小相等的小数据块(Hadoop2.x 中默认128MB),也就是分片(split-逻辑分块,而block物理分块,两者默认情况是一一对应的),Hadoop会为每一个分片构建一个Map任务,并由该任务运行自定义的map()数,从而处理分片里的每一条记录;
- 格式化操作:将划分好的分片(split)格式化为键值对<key,value>形式的数据,其中,key代表偏移量,value代表每一行内容。
执行MapTask
每个Map任务都有一个内存缓冲区(缓冲区大小100MB),输人的分片(split)数据经过Map任务处理后的中间结果会写人内存缓冲区中。如果写人的数据达到内存缓冲的國值(80MB),会启动一个线程将内存中的溢出数据写人磁盘,同时不影响map中间结果继续写人缓冲区。在溢写过程中,MapReduce框架会对key进行排序,如果中间结果比较大,会形成多个溢写文件,最后的缓冲区数据也会全部溢写人磁盘形成一个溢写文件,如果是多个溢写文件,则最后合并所有的溢写文件为一个文件·
执行Shuffle过程
MapReduce工作过程中,Map阶段处理的数据如何传递给Reduce阶段,这是MapReduce框架中关键的一个过程,这个过程叫作Shuffle.Shuffle会将MapTask输出的处理结果数据分发给ReduceTask,并在分发的过程中,对数据按key进行分区和排序。关于Shuffle过程的具体机制.详见4.2.节。
执行ReduceTask–合并
输人ReduceTask的数据流是**<key,{value list}>形式,用户可以自定义reduce()方法进行逻辑处理,最终以<key,value>**的形式输出·
写入文件
MapReduce框架会自动把ReduceTask生成的<key,value>传入OutputFormat的write方法,实现文件的写入操作。

4.2.2 MapTask 工作原理

MapTask作为MapReduce工作流程的前半部分,它主要经历了5个阶段,分别是Read阶段、Map阶段、Collect阶段、Split阶段和Combine阶段,如图4.7所示。
在这里插入图片描述

  1. Read阶段:MapTask通过用户编写的RecordReader,从输人的InputSplit中解析出一个个key/value。
  2. Map阶段:将解析出的key/value交给用户编写的map()函数处理,并产生一系列新的key/value
  3. Collect阶段:在用户编写的map()函数中,数据处理完成后,一般会调用outputCollector.collect0输出结果,在该函数内部,它会将生成的key/value分片(通过调用partitioner),并写人一个环形内存缓冲区中。
  4. Spill阶段:即“溢写”,当环形缓冲区后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写人本地磁盘前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作.
  5. Combine阶段:当所有数据处理完成以后,MapTask会对所有临时文件进行一次合并,以确保最终只会生成一个数据文件

4.2.3 PreduceTask 工作原理

ReduceTask的工作过程主要经历了5个阶段,分别是Copy阶段、Merge阶段、Sort阶段、Reduce阶段和Write阶段,如图4.8所示。
在这里插入图片描述

  1. Copy阶段:Reduce会从各个MapTask上远程复制一片数据,并针对某一片数据,如果其大小超过一定國值,则写到磁盘上,否则直接放到内存中。
  2. Merge阶段:在远程复制数据的同时,ReduceTask会启动两个后台线程,分别对内存磁盘上的文件进行合并,以防止内存使用过多或者磁盘文件过多。
  3. Sort阶段:用户编写reduce()方法输人数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。
  4. Reduce阶段:对排序后的键值对调用reduce()方法,键相等的键值对调用一次reduce()方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写人到HDFS中。
  5. Write阶段:reduce()函数将计算结果写到HDFS上。

4.2.4 Shuffle 工作原理

Shuffle是MapReduce的核心,它用来确保每个Reducer的输人都是按键排序的。它的性能高低直接决定了整个MapReduce程序的性能高低。接下来,通过一个图来描述Shuffle过程,具体如图4-9所示。
在这里插入图片描述
在图1一9中,MapReduce阶段都涉及了Shuffle机制,接下来,分别进行分析,具体如下:

  1. Map阶段
    1. MapTask处理的结果会暂且放人一个内存缓冲区中(该缓冲区默认大小是100(B),当缓冲区快要溢出时(默认达到缓冲区大小的80%),会在本地文件系统创建一个溢出文件,将该缓冲区的数据写人这个文件。
    2. 写人磁盘之前,线程会根据ReduceTask的数量,将数据分区,一个Reduce任务对应一个分区的数据。这样做的目的是为了避免数据倾斜(有些reduce任务分配到大量数据,而有些reduce任务分到很少的数据,甚至没有分到数据的尴尬局面)。
    3. 分完数据后,会对每个分区的数据进行排序,如果此时设置了Combiner,将排序后的结果进行Combine操作,这样做的目的是尽可能少地执行数据写人磁盘的操作。
    4. 当Map任务输出最后一个记录时,可能有很多溢出文件,这时需要将这些文件合并,合并的过程中会不断地进行排序和Combine操作,其目的有两个:一是尽量减少每次写人磁盘的数据量;二是尽量减少下一复制阶段网络传输的数据量。最后合并成了一个已分区且已排序的文件。
    5. 将分区中的数据复制给对应的Reduce任务。
  2. Reduce阶段
    1. Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果Reduce阶段接收的数据量相当,则直接存储在内存中,如果数据量超过了该缓冲区大小的一定比例,则对数据合并溢写到磁盘中。
    2. 随着溢写文件的增多,后台线程会将它们合并成一个更大的有序的文件,这样做是为了给后面的合并节省时间。
    3. 合并的过程中会产生许多的中间文件(写入磁盘了),但MapReduce会让写人磁盘的数据尽可能地少,并且最后一次合并的结果并没有写人磁盘,而是直接输人到reduce函数。

4.4 MapReduce 运行模式

MapReduce程序的运行模式主要有如下两种。

  1. 本地运行模式:在当前的开发环境模拟MapReduce执行环境,处理的数据及输出结果在本地操作系统
  2. 集群运行模式:把MapReduce程序打成一个jar包,提交至YARN集群上去运行任务。由于YARN集群负责资源管理和任务调度,程序会被框架分发到集群中的节点上并发地执行,因此处理的数据和输出结果都在HDFS中。集群运行模式只需要将MapReduce程序打成jar包上传至集群即可,比较简单

4.5 MapReduce性能优化策略

使用Hadoop进行大数据运算,当数据量极大时,那么对MapReduce性能的调优重要性不言而喻,尤其是Shuffle过程中的参数配置对作业的总执行时间影响特别大。下面总结一些和MapReduce相关的性能调优方法,主要从5个方面考虑:数据输人、Map阶段、Reduce阶段、Shuffle阶段和其他调优属性,

  1. 数据输入
    在执行MapReduce任务前,将小文件进行合并,大量的小文件会产生大量的map任务,增大map任务装载的次数,而任务的装载比较耗时,从而导致MapReduce运行速度较慢。因此采用CombineTextInputFormat来作为输人,解决输人端大量的小文件场景。
  2. Map阶段
    1. 减少溢写(spill)次数:通过调整io.sort.mb及sort.split.percent参数值,增大触发spill的内存上限,减少split次数,从而减少磁盘I/O
    2. 减少合并(mee)次数:通过调整io.sort.factor参数,增大merge的文件数目,减少merge的次数,从而缩短mr处理时间。
    3. 在map之后,不影响业务逻辑前提下,先进行combine处理减少I/O
      上面提到的那些属性参数,都是位于mapred-default.xml文件中,这些属性参数的调优方式如表4一1所示。
      在这里插入图片描述
  3. Reduce阶段
    1. 合理设置map和reduce数:两个都不能设置太少,也不能设置太多。太少,会导致task等待,延长处理时间太多,会导致map和reduce任务间竞争资源,造成处理超时等错误.
    2. 设置map和reduce共存:调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间·
    3. 规避使用reduce:因为reduce在用于连接数据集的时候将会产生大量的网络消耗。通过将MapReduce参数setNumReduceTasks设置为0来创建一个只有map的作业。
    4. 合理设置reduce端的buffer:默认情况下,数据达到一个阈值的时候,buffer中的数据就会写人磁盘,然后reduce会从磁盘中获得所有的数据。也就是说,buffer和reduce是没有直接关联的,中间多一个写磁盘一·读磁盘的过程,既然有这个弊端,那么就可以通过参数来配置.使得buffer中的一部分数据可以直接输送到reduce,从而减少I/O开销。这样一来,设置buffer需要内存,读取数据需要内存,red计算也要内存,所以要根据作业的运行情况进行调整。
      上面提到的属性参数,都是位于mapred-default.xml文件中,这些属性参数的调优方式如表4一2所示。
      在这里插入图片描述
  4. Shuffle阶段
    Shuffle阶段的调优就是给Shuffle过程尽量多地提供内存空间,以防止出现内存溢出现象,可以由参数mapred.child.java.opts来设置,任务节点上的内存大小应尽量大。
    上面提到的属性参数,都是位于mapred-site.xml文件中,这些属性参数的调优方式如表4.3所示。

在这里插入图片描述

  1. 其他调优属性
    除此之外,MapReduce还有一些基本的资源属性的配置,这些配置的相关参数都位于mapred-default.xml文件中,可以合理配置这些属性提高MapReduce性能,表4一4列举了部分调优属性。
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值