19

我想我总体上对 MapReduce 编程模型有一个公平的理解,但是即使在阅读了原始论文和其他一些资料之后,我也不清楚许多细节,尤其是关于中间结果的划分。

我将快速总结一下到目前为止我对 MapReduce 的理解:我们有一个可能非常大的输入数据集,它被 MR-Framework 自动分成 M 个不同的部分。对于每一部分,框架都会安排一个地图任务,该任务由我的集群中的一个可用处理器/机器执行。M 个 map 任务中的每一个都输出一组 Key-Value-Pairs,它们本地存储在执行该 map 任务的同一台机器上。每台机器将其磁盘划分为 R 个分区,并根据分区之间的中间键分配其计算的中间键值对。然后,框架为每个不同的中间键启动一个 reduce 任务,该任务再次由任何可用机器执行。

现在我的问题是:

  1. 在某些教程中,听起来好像可以并行执行 map 和 reduce 任务。这是正确的吗?假设对于每个不同的中间键,只启动一个 reduce 任务,这怎么可能呢?我们不是必须等到最后一个 map 任务完成后才能开始第一个 reduce 任务吗?
  2. 由于我们每个不同的中间键都有一个reduce任务,每个reduce任务都需要执行机器从其他机器加载相应的分区是否正确?潜在地,每台机器都可以有一个带有所需中间键的键值对,因此对于每个 reduce 任务,我们可能必须查询所有其他机器。真的有效率吗?
  3. 原始论文说分区数(R)由用户指定。但是分区不是reduce任务的输入吗?或者更准确地说:所有机器中具有相同数量的所有分区的并集不是一个reduce任务的输入吗?这意味着,R 取决于用户通常不知道的不同中间键的数量。

从概念上讲,map 和 reduce 函数/任务的输入和输出是什么很清楚。但是我想我还没有在技术层面上理解 MapReduce。有人可以帮我理解吗?

4

2 回答 2

12
  1. 您可以在 map 任务仍在运行时启动 reducer 任务(使用称为 slowstart 的功能),但 reducer 只能运行复制阶段(从已完成的 map 任务中获取已完成的结果。它需要等待所有mappers 在它实际执行最终排序和归约之前完成。
  2. reduce 任务实际上处理零个、一个或多个键(而不是每个键的离散任务)。在对这些中间输出进行排序之前,每个 reducer 都需要从每个与其分区相关的 map 任务中获取 map 输出,然后一次减少一个 key 集。
  3. 回到 2 中的注释 - 一个 reducer 任务(每个分区一个)在零个、一个或多个键上运行,而不是每个离散键的单个任务。

了解中间键的分布和变化也很重要,因为它是散列和取模的(如果使用默认的 HashPartitioner)以确定哪个减少分区应该处理该键。假设您有偶数个减速器任务(10),并且输出键总是散列为偶数 - 那么在这种情况下,这些散列数和 10 的模将始终是偶数,这意味着奇数减速器将从不处理任何数据。

于 2013-07-19T11:00:33.357 回答
8

克里斯所说的附录,

基本上,Hadoop 中的分区器类(例如 Default HashPartitioner

必须实现这个功能,

int getPartition(K key, V value, int numReduceTasks) 

该函数负责返回分区号,并且您在从numReduceTasks变量启动作业时获得固定的减速器数量,如 HashPartitioner 中所示。

根据上述函数返回的整数,Hadoop 选择运行特定键的 reduce 任务的节点。

希望这可以帮助。

于 2013-07-19T11:26:21.453 回答