Hadoop系列-MapReduce架构和工作原理简介(十一)

一、MapReduce 简介

 MapReduce 是 Hadoop 生态下面的计算层,它把任务分割成小任务并分发到集群的机器上并行执行。您只需要按照 MapReduce 提供的编程接口开发业务逻辑代码即可,剩下的事情 MapReduce 框架会自动完成。比如,任务分割,任务分发等。MapReduce 程序具有函数式风格,输入是数据列表,输出依然是数据列表。MapReduce 是 Hadoop 的核心。Hadoop 如此强大就是因为 MapReduce 的并行处理能力。

了解 Hadoop MapReduce

MapReduce 是如何工作的呢?

MapReduce 会把打任务分成小任务,每个小任务可以在集群并行执行。每个小任务都会输出计算结果,这些结果数据后续被汇总并输出最终结果。

Hadoop MapReduce 具有较好的扩展性,它可以在很多机器上跑。集群里面单个机器可能无法执行大任务,但可以执行大任务分割后的小任务。这是 MapReduce 比较核心的机制。

Apache MapReduce 术语

本节主要介绍 MapReduce 相关概念和术语。如,什么是 Map 和 Reduce,什么是 job,task,task attempt 等。

MapReduce 是 Hadoop 的数据处理组件。MapReduce 程序把输入数据转换成特定格式的输出数据。一个 MapReduce 程序主要就做下面这两步:

  • Map
  • Reduce

在 Map 和 Reduce 中间还有一个处理阶段,叫做 Shuffle 和 排序操作。

下面介绍一下 MapReduce 里面的一些关键术语。

  • 什么是 MapReduce Job(作业)?

一个 MapReduce Job 过程分成两个阶段:Map 阶段和 Reduce 阶段。每个阶段都用 key/value 作为输入和输出;每个阶段都需要定义函数,也就是 map 函数和 reduce 函数;可以简单认为 map 函数是对原始数据提出出有用的部分,而 reduce 函数则是对提取出来的数据进行处理。

  • 什么是 MapReduce Task

MapReduce 里面的 task 可以分两种,即 Map task 和 Reduce task,即处理分片数据的 Mapper 和 Reducer 任务,这里的 Mapper 和 Reducer 的业务逻辑由开发者定义。

  • 什么是 Task Attempt

Task Attempt,即任务尝试。集群的机器在任何时间都可能发生故障,比如,正在处理数据的机器挂了,MapReduce 把任务重新调度到其他机器节点。当然这里的重新调度次数并非不受限制的,它是有上限的,默认是 4 次,如果一个任务(Mapper 任务或者 Reducer 任务)失败 4 次,那么整个 Job 就被认为失败了。对于高优先级的作业或者大型作业,这个值可以调高一点。

Map 阶段

map 函数以键值对作为输入数据,不管数据是结构化还是非结构化,框架都会把数据转换成键值对形式。键是输入值的引用,而值就是要操作的数据集。

用户可以根据业务需求开发特定的业务逻辑来实现 MapReduce 框架的 map 函数。map 函数会对每个输入键值对的值部分处理。处理之后会生成输出结果,map 的输出叫做中间输出,它的类型可能与输入键值不同。map的输出结果是存储在本地磁盘的。

Reduce 阶段

Reduce 以 Map 的输出结果作为输入数据,并对这些数据进行处理。通常,在 reducer 我们会做聚合或求和计算。另外,MapReduce 给 reduce 的输入数据按键做排序操作。

用户可以根据业务需求开发特定的业务逻辑来实现 MapReduce 框架的 reduce 函数,reduce 函数对输入值做聚合操作,并输出最终结果写入到 HDFS。

Map 和 Reduce 是如何一起工作的

Hadoop系列-MapReduce架构和工作原理简介(十一)_第1张图片


输入数据被分割成分片,并提供给 mapper 处理,当然,具体的 mapper 的业务逻辑需要用户来实现。所有必要的复杂的业务逻辑都在 mapper 层面实现了,繁琐的处理都由并行的 mapper 来处理了,所以,mapper 的数量要比 reducer 的数量多不少。Mapper 生成输出结果,即中间数据, 而 Reducer 以这些中间数据作为输入,具体的 Reducer 逻辑也是需要您来实现的。通常,Reducer 的逻辑相对比较简单。Reducer 执行完之后,最终结果就生成了,并且最终会存储在 HDFS。

MapReduce 数据流程

现在让我们来看看 MapReduce 完整的数据流程,本节您将对以下问题有跟更清晰的概念:
输入数据是如何给到 mapper 的?
mapper 是如何处理数据的?
mapper 把数据结果写到哪里?
数据是如何从 mapper 流向 reducer 节点的?
reducer 在哪里执行?
reducer 将完成哪种类型的处理?

Hadoop系列-MapReduce架构和工作原理简介(十一)_第2张图片


MapReduce 的大概的工作流程如上图所示,其中方块表示 slave 节点,所以这里有 3 个 slave 节点。 mapper 运行在 3 个 slave节点上,而 reducer 在任意一个slave 运行,上图为了简单起见,把 reducer 进程画在一个方块里,看起来是运行在一个不同的机器上,其实它是在 mapper 的节点上运行的。

Mapper 是 MapReduce 作业的第一个执行阶段。默认情况下,一个 mapper 每次处理的分片数据(split)都是一个 HDFS 数据块,mapper 的输出数据会被写到本地机器的磁盘上。mapper 跑完之后,mapper 输出的结果数据会到 reducer 节点,即运行 reducer 的机器。

Reducer 是 MapReduce 作业的 第二个执行阶段。它的计算结果将会直接落地到 HDFS。

在默认情况下,一个 slave 每次可以跑 2 个 mapper(可以根据需要调高这个值),而 slave 同时能跑多少个 mapper 取决于很多因素,比如,机器的硬件配置,HDFS 块大小等。所以建议不要把这个值调太高,因为这会降低 MapReduce 运行性能。

MapReduce 的 Mapper 会把它的输出结果写到本地磁盘。这个输出结果是临时数据,也叫做中间输出结果。所有的 mapper 都会把输出数据写到本地磁盘。mapper 执行完之后,mapper 输出的数据会从 mapper 节点传输到 reducer 节点,这个过程被称为 shuffle

Reducer 也是运行在集群的任意一个 datanode 的。所有 mapper 的输出数据都会到 reducer。这些来自不同 mapper 的输出数据会被合并,并作为 reducer 的输入数据。这些合并后的数据还是存储在 mapper 所在节点的磁盘的。Reducer 是 MapReduce 框架提供的另一个你能实现自己业务逻辑的接口,通常我们会在 Reducer 做数据聚合,相加等操作。因此,Reducer 会把最终结果数据写到 HDFS。

map 和 reduce 是执行 MapReduce 作业的两个数据处理阶段。所有 mapper 执行完之后,reducer 才能开始执行。

虽然默认情况下 1 个块会存储在 3 个不同的位置,但 1 个 mapper 只处理其中的一个块。每个 mapper 的输出数据都会被传输到 reducer,因此,只有在所有的 mapper 处理完所有数据之后,reducer 才能开始处理数据。

mapper 输出数据会被 partitioner 按 key 进行分区。每个分区会基于某些条件被传输到一个 reducer。MapReduce 的工作是基于 key-value (键值对)原则的,比如,mapper 和 reducer 输入数据是键值对数据,输出同样也是键值对数据。MapReduce 数据流程是 MapReduce 框架最重要的一部分。后续章节还会详细介绍。

MapReduce 的数据本地化

本节让我们理解一下什么是数据本地化,它是如何提升 MapReduce Job 的性能的。

移动计算比移动数据更高效

代码在离它运算的数据最近的地方执行更加高效,特别在数据量大的情况下代码执行效率提升更加明显。因为移动代码消耗的网络带宽,要远远比移动大量数据消耗的带宽资源小很多。因此,HDFS 给 MapReduce 提供了一个接口,用于把代码移动到离数据最近的地方。

因为 Hadoop 处理的数据量都比较大,经常通过网络传输大数据量并不现实,因此,它提出了一个极具创新的原则,即把计算移动到离数据最近的地方执行,而非相反,这就是我们所说的数据本地化。

二、MapReduce 工作原理

本节主要详细介绍 MapReduce 的工作原理。

Hadoop系列-MapReduce架构和工作原理简介(十一)_第3张图片

上面这个流程图已经把 MapReduce 的工作过程说的很清楚了,下面我们来一个一个拆解一下。

输入文件

首先,MapReduce 任务的目的是处理数据,那数据从哪里来?一般一个 MapReduce 任务的输入数据是来自于 HDFS 文件,这里的数据文件就叫做 MapReduce 任务的输入文件,而 HDFS 上文件的格式多种多样,比如有文本文件,二进制文件等。

InputFormat

InputFormat 是 MapReduce 框架的一个类,它对输入文件进行分割和读取,并创建数据分片 InputSplit。

InputSplit

InputSplit 对象即数据分片对象,由 InputFormat 生成的,一个数据分片由一个 Mapper 来处理,数据分片是逻辑上的划分,并非物理分割。每一个分片都会相应创建一个 map 任务,因此,map 任务的数量等于分片的数量,即有多少个分片就有多少个 map 任务。分片会被划分成记录,并且每个记录都会被对应 mapper 处理。

RecordReader

它会跟 InputSplit 交互,并把数据转换成适合 mapper 读取的键值对(key-value pair)记录。默认情况下,它用的是 TextInputFormat 类来做转换。RecordReader 与 InputSplit 交互一直到文件读取完成。它会给文件的每一行数据分配一个字节偏移量(byte offset)作为唯一编号。后续这些键值对将被发送给 mapper 做进一步处理。

Mapper

它负责处理每一个来自 RecordReader 的记录,并生成新的键值对数据,这些 Mapper 新生成的键值对跟输入键值对是不一样的。Mapper 的输出也就是我们前面说的中间结果将会被写到本地磁盘。Mapper 的输出数据并不是存储在 HDFS 的,因为这是临时数据,如果把临时数据写到 HDFS ,将造成不必要的复制,会导致 map 任务性能低下。Mapper 的输出数据被传输给 Combiner 做下一步处理。

Combiner

combiner 其实是一种 reduce 操作。它会对 mapper 的输出数据做本地聚合,也就是说它是在输出数据的 mapper 所在的机器上执行的。主要为了减少 mapper 和 reducer 之间的数据传输。combiner 执行完成之后,它的输出结果就会被传输到 partitioner 做下一步处理。

Partitioner

如果一个 MapReduce 作业在 reduce 阶段有多个 reducer 任务参与,才会有 Partitioner 这一步,即数据分区。如果只有一个 reducer 任务,Partitioner 是不会执行的,即不会对数据分区。

Partitioner 对来自 combiner 的输出数据分区并排序,其实就是对数据的 key 做哈希运算,具有相同 key 的记录会被分到相同的分区,然后每个分区会被发送给 reducer。

Shuffle 和排序

现在,Partitioner 的输出被 shuffle 到 reduce 节点( 这里的 reduce 节点其实就是正常的 slave 节点,由于在上面跑 reduce 任务所以才叫 reduce 节点)。shuffle 是对数据进行跨网络的物理移动,需要消耗网络带宽资源。在所有 mapper 都完成之后,他们的输出数据才会被 shuffle 到 reduce 节点,并且这些 mapper 产生的数据会被合并和排序,然后作为 reduce 阶段的输入数据。

Reducer

在 reduce 阶段,它把 mapper 输出的键值对数据作为输入,然后对每个键值对数据记录应用 reducer 函数并输出结果。reducer 的输出数据是 MapReduce 作业的最终计算结果,它会被存储到 HDFS。

RecordWrite

它负责把来自 Reducer 输出的键值对数据写到输出文件。

OutputFormat

RecordWriter 将 Reducer 输出的键值对写入输出文件的方式由 OutputFormat 决定。OutputFormat 是由 Hadoop 提供的用于把数据写到 HDFS 或者本地磁盘的接口。因此,reducer 的最终输出数据是由 Outputformat 实例负责写入到 HDFS 的。

以上就是 MapReduce 完整的工作流程了。后续的教程会对每个步骤进行详细分析。


参考文章:MapReduce 工作原理 | MapReduce 教程

你可能感兴趣的:(Hive,&,Hadoop,MapReduce工作原理)