MapReduce流程浅析

本文深入解析了Hadoop的MapReduce模型,包括其核心组件Map和Reduce函数的运作机制,以及Shuffle过程的详细步骤。通过WordCount实例,展示了如何将复杂的大规模数据处理任务分解并并行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

Hadoop是一个实现了Google云计算系统的开源系统,包括并行计算模型Map/Reduce、分布式文件系统HDFS,以及分布式数据库Hbase,同时Hadoop的相关项目也很丰富,包括ZooKeeper、Pig、Chukwa、Hive、Hbase、Mahout、flume等。

这里,我们明确了MapReduce是一个分布式并行编程框架,它将复杂的、运行于大规模集群上的并行计算过程高度地抽象到两个函数:Map和Reduce。

注意,适合用MapReduce来处理的数据集需要满足一个前提条件:待处理的数据集可以分解成许多小的数据集,而且每一个小数据集都可以完全并行地进行处理。

Map和Reduce函数

MapReduce模型的核心是Map函数和Reduce函数,这两者需要我们自己来实现!两者都是以键值对作为输入,按一定的映射规则转换成另一个或一批键值对进行输出。

Map函数的输入来自于分布式文件系统的文件块,这些文件块的格式是任意的。Map函数将输入的元素转换成键值对的形式,键和值的类型也是任意的。这个键没有唯一性。

Reduce函数的任务就是将输入的一系列具有相同键的键值对以某种方式组合起来,输出处理后的键值对,输出结果会合并成一个文件。

MapReduce的工作流程

工作流程概述

MapReduce的核心思想就是“分而治之”。如下图所示,将大的数据块分成小的数据块在多台机器上并行处理,也就是一个大的MapReduce作业,首先被拆分成多个Map任务在多个机器上并行执行,每个Map任务通常运行在数据存储的节点上,这样数据和计算在一起,不会产生数据搬运的开销。当Map任务结束后,会生成以<key,value>形式的中间结果。这些结果会被分发到多个Reduce任务在多台机器上并行执行,就有相同key的<key,value>会被发送到同一个Reduce任务那里,Reduce任务会对中间结果进行汇总计算得到最后结果,并输出到分布式文件系统。

Map任务的输入文件和Reduce任务的输出文件都是保存在分布式文件系统的,而Map任务处理得到的中间结果则保存在本地存储中。

MapReduce的各个执行阶段

  1. MapReduce框架使用InputFormat模块做Map前的预处理,然后将文件切分为逻辑上的多个InputSplit,InputSplit是MapReduce对文件进行处理和运算的输入单位,只是一个逻辑概念,没有进行实际的切割,只是记录了要处理 的数据的位置和长度。
  2. 由于InputSplit只是逻辑上的切割,后面就需要通过RecordReader(RR)根据InputSplit中的信息来处理InputSplit中的具体记录,加载数据并转换为适合Map任务读取的键值对,输入给Map任务。
  3. Map任务根据用户定义的映射规则,输出一系列的<key,value>作为中间结果。
  4. 为了让Reduce可以并行处理Map的结果,需要对Map的输出进行一定的分区(Portition)、排序、合并(Combine)、归并(Merge)等操作,得到<key,value-list>形式的中间结果,再交给对应的Reduce进行处理,这个过程称为Shuffle。
  5. Reduce以一系列<key,value-list>中间结果作为输入,执行用户定义的逻辑,输出结果给OutputFormat模块。
  6. OutputFormat模块会验证输出目录是否已经存在以及输出结果类型是否符合配置文件中的配置类型,如果满足,就输出Reduce的结果到分布式文件系统。

Shuffle过程详解

所谓Shuffle,是指Map输出结果进行分区、排序、合并等处理并交给Reduce的过程,流程图如下。

  1. Map端的shuffle

<1>输入数据和执行Map任务

Map任务的数据数据一般保存在分布式文件系统的文件块中,这些文件的格式是任意的。Map任务接收<key,value>作为输入后,按一定的映射规则转换成一批<key,value>进行输出。

<2>写入缓存

每个Map任务还会分配一个缓存,Map的结果不立即写入磁盘,而是放在缓存中,当缓存中的数据积累到一定的量,再一次性的写入磁盘,这样可以减小对磁盘IO的开销。

<3>溢写(分区、排序和合并)

提供给缓冲的空间是有限的,随着Map的执行,就需要清空缓存,将缓存的数据写入磁盘。在写入磁盘之前,会对数据进行分区(Partition)。缓存中的数据是<key,value>形式的键值对,这些键值对最终需要交给不同的Reduce任务进行处理。MapReduce通过Partitioner接口对这些键值对进行分区,默认采用Hash函数对Key进行哈希互殴再用Reduce任务的数量取模。

对于每个分区内的所有键值对,后台线程会根据key对它们进行内存排序,排序是Map Reduce的默认操作。排序结束后,还包含一个可选的合并(Conbine)操作。如果进行了合并操作,则可以减少需要溢写到磁盘的数据量。

<4>文件归并

最终,在Map任务全部结束之前,系统会对所有溢写文件中的数据进行归并,生成一个大的溢写文件,这个大的溢写文件中的所有键值对也是经过分区和排序的。所谓归并,是指将具有相同Key的键值对会归并成一个新的键值对。具体而言就是将<key,v1>、<key,v2>...<key,vn>归并为<key,<v1,v2,...vn>>。

2、Reduce端的Shuff过程

<1>领取数据

Map端的Shuff过程结束后,所有的Map输出结果保存在本地的磁盘上,Reduce会将这些数据领取放在自己所在机器的本地磁盘上。每个Reduce任务不断的通过RPC向JobTracker询问Map任务是否完成;JobTracke监测到Map的任务完成后,就会通知Reduce任务来取数据;一旦收到通知,就会到该Map任务所在的机器上把数据自己处理的分区的数据领取到自己的本地磁盘上。

<2>归并数据

系统中存在多个Map任务,Reduce任务会从多个Map机器上领回属于自己的分区数据,因此在Reduce的机器缓冲中的数据来自不同的Map机器,这些数据也需要进行归并操作,在归并的时候同样也会进行排序操作。

<3>把数据输入给Reduce任务

磁盘中经过多轮归并后得到若干个大文件,不会归并为一个新的大文件,而是直接输出给Reduce任务,这样可以减少磁盘读写开销。由此,整个shuffle过程结束。接下来,Reduce任务会执行Reduce函数中定义的各种映射,输出最终结果,并保存到分布式文件系统中。

实例分析

我们可以从word count这个实例来理解MapReduce。

1、输入(input):如给定一个文档,包含如下四行

Hello Java

Hello C

Hello Java

Hello C++

2、拆分(split):将上述文档中每一行的内容转换为key-value对,即:

0 - Hello Java

1 - Hello C

2 – Hello Java

3 - Hello C++

3、映射(map):将拆分之后的内容转换成新的key-value对,即:

(Hello , 1)

(Java , 1)

(Hello , 1)

(C , 1)

(Hello , 1)

(Java , 1)

(Hello , 1)

(C++ , 1)

4、派发(shuffle):将key相同的扔到一起去,即:

(Hello , 1)

(Hello , 1)

(Hello , 1)

(Hello , 1)

(Java , 1)

(Java , 1)

(C , 1)

(C++ , 1)

注意:这一步需要移动数据,原来的数据可能在不同的datanode上,这一步过后,相同key的数据会被移动到同一台机器上。最终,它会返回一个list包含各种k-value对,即:

{ Hello: 1,1,1,1}

{Java: 1,1}

{C: 1}

{C++: 1}

5、缩减(reduce):把同一个key的结果加在一起。如:

(Hello , 4)

(Java , 2)

(C , 1)

(C++,1)

6、输出(output): 输出缩减之后的所有结果。

参考文章

https://www.zhihu.com/question/23345991

《大数据技术原理与应用》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值