【问题标题】:What is the purpose of shuffling and sorting phase in the reducer in Map Reduce Programming?Map Reduce编程中reducer中的shuffle和sorting阶段的目的是什么?
【发布时间】:2014-04-04 04:45:26
【问题描述】:

在 Map Reduce 编程中,reduce 阶段包含 shuffle、sorting 和 reduce 作为其子部分。排序是一件昂贵的事情。

Map Reduce编程中reducer中shuffle和sort阶段的目的是什么?

【问题讨论】:

  • 我一直认为这是必要的,因为 mapper 的输出是 reducer 的输入,所以它根据 keyspace 进行排序,然后为每个 reducer 输入拆分成桶。

标签: sorting hadoop mapreduce hdfs shuffle


【解决方案1】:

首先shuffling是将数据从mapper传输到reducer的过程,所以我认为reducer显然是有必要的,否则他们将无法有任何输入(或来自每个映射器的输入)。洗牌甚至可以在地图阶段完成之前开始,以节省一些时间。这就是为什么当地图状态还不是 100% 时,您会看到大于 0%(但小于 33%)的 reduce 状态。

Sorting 为 reducer 节省了时间,帮助它轻松区分何时应该开始新的 reduce 任务。它只是启动一个新的 reduce 任务,当排序后的输入数据中的下一个 key 与上一个不同时,简单地说。每个reduce任务都接受一个键值对列表,但它必须调用reduce()方法,该方法接受一个键列表(值)输入,因此它必须按键对值进行分组。如果输入数据在 map 阶段(本地)预先排序并在 reduce 阶段简单地合并排序(因为 reducer 从许多 mapper 获取数据),那么这样做很容易。

您在其中一个答案中提到的Partitioning 是一个不同的过程。它确定将在哪个reducer 中发送(key, value) 对,即map 阶段的输出。默认的 Partitioner 对键使用散列来将它们分配给 reduce 任务,但您可以覆盖它并使用您自己的自定义 Partitioner。

Yahoo tutorial (archived) 是这些步骤的重要信息来源。

一个很好的图形表示如下(在该图中,随机播放称为“复制”):

请注意,如果您指定零减速器 (setNumReduceTasks(0)),则根本不会执行 shufflingsorting。然后,MapReduce 作业在 map 阶段停止,并且 map 阶段不包括任何类型的排序(因此即使是 map 阶段也更快)。

更新:由于您正在寻找更官方的东西,您还可以阅读 Tom White 的书“Hadoop:权威指南”。 Here 是您问题的有趣部分。
Tom White 自 2007 年 2 月以来一直是 Apache Hadoop 提交者,并且是 Apache 软件基金会的成员,所以我想这是相当可信和官方的......

【讨论】:

  • "排序为reducer节省了时间,帮助它轻松区分什么时候应该开始一个新的reduce任务。它只是启动一个新的reduce任务,当排序后的输入数据中的下一个key与前一个不同时, 简而言之。”我不明白这部分。 Mapper 使用分区器将溢出划分为本地分区,然后将每个分区发送到 reduce。排序在这里有什么帮助?
  • @MaxNevermind 如果您有 x 个 reduce 任务(分区),这并不意味着您最终会调用 x 次 reduce() 方法。它将为每个不同的键调用一次。所以一个reduce任务可以多次调用reduce()方法。
  • "它将为每个不同的键调用一次" 为什么? Mapper 以任何它想要的方式形成分区(不必为每个不同的 key 一个分区),然后每个分区都进入 reducer,是不是错了?
  • @MaxNevermind Mapper 输出键和值,它不形成分区。分区由用户定义的 reduce 任务的数量和 Partitioner 实现定义。所有具有相同键的 Mapper 的输出都将转到相同的 reduce() 方法。这是无法改变的。但是可以改变的是其他键(如果有的话)将被放置在同一分区中,因此将由同一任务处理。 reduce 任务可以多次调用 reduce() 函数,但每个键只能调用一次。
  • 好的,我想我明白了。我的问题是我忘记了 reduce 将值列表作为参数,而不仅仅是一个键值对。我认为你应该在你的回答中详细说明:“每个reduce任务都需要一个键值对列表,但它必须调用reduce方法,它需要一个key-List,所以它必须按键对值进行分组,这很容易如果输入数据在映射器阶段预先排序"
【解决方案2】:

让我们回顾一下 Mapreduce 程序的关键阶段。

映射阶段由映射器完成。 Mappers 在未排序的输入键/值对上运行。每个映射器为每个输入键/值对发出零个、一个或多个输出键/值对。

组合阶段由组合器完成。 combiner 应该将键/值对与相同的键组合起来。每个组合器可以运行零次、一次或多次。

洗牌和排序阶段由框架完成。来自所有映射器的数据按 key 分组,在 reducer 之间拆分并按 key 排序。每个 reducer 获取与同一个键关联的所有值。程序员可以提供用于排序的自定义比较函数和用于数据拆分的 partitioner

partitioner 决定哪个reducer 将获得特定的键值对。

reducer 获得排序后的 key/[values list] 对,按 key 排序。值列表包含映射器生成的具有相同键的所有值。每个reducer 为每个输入键/值对发出零个、一个或多个输出键/值对

看看这个 javacodegeeks article by Maria Jurcovicova 和 mssqltips Datta 的文章以获得更好的理解

下图来自safaribooksonline文章

【讨论】:

  • 我认为图像中有错字(我意识到只是在这里复制)。我相信 Reducers 和 Output 下的 ie 字符串实际上应该是 is
  • 你能告诉我为什么映射器需要偏移量,因为该偏移量的值将在“值”部分可用吗?
【解决方案3】:

我想只是在上面的答案中添加一些缺失的点。这张来自here 的图表清楚地说明了实际情况。

如果我再说一遍真正的目的

  • 拆分:通过将处理负载分布到不同节点(映射器)来改进并行处理,这将节省整体处理时间。

  • 组合:缩小每个映射器的输出。这将节省将数据从一个节点移动到另一个节点所花费的时间。

  • 排序(Shuffle & Sort) 使运行时可以轻松地安排(生成/启动)新的 reducer,在遍历排序的项目列表时,只要当前key 和之前的不一样,它可以产生一个新的 reducer。

【讨论】:

  • 分区步骤会出现在该图中的什么位置?地图之后和合并之前?
  • @Joel 我希望您指的是“拆分”步骤?
  • 不,我的意思是分区步骤,它决定将数据发送到哪个reducer,默认情况下使用简单的哈希模数,经过更多研究,我相信它在组合步骤之后,在随机排序和排序之前.
  • @Joel 我不太清楚你打算描述什么。简而言之,确切的步骤顺序几乎是针对特定问题的。我可以说,在某些情况下,甚至不需要排序。回到您的输入,如果我专门讨论上述简单的字数示例,我真的认为不需要这样的分区来决定减速器。在这里,每个键的产生减少非常简单。但我可以猜到你的观点在某些情况下是有效的。坦率地说,我对此并没有一个明确的概念。
  • @rahulsharma 整个 map-reduce 系统遵循主从协调。因此,每个节点间的操作都基于此。
【解决方案4】:

某些数据处理要求根本不需要排序。 Syncsort 使 Hadoop 中的排序成为可插拔的。 Here 是他们关于排序的一个不错的博客。将数据从 mapper 移动到 reducer 的过程称为 shuffle,查看this 文章了解更多信息。

【讨论】:

    【解决方案5】:

    我一直认为这是必要的,因为 mapper 的输出是 reducer 的输入,因此它根据 keyspace 进行排序,然后为每个 reducer 输入拆分成桶。您希望确保 Key 的所有相同值最终都在同一个桶中进入减速器,以便它们一起减少。将 K1,V2 和 K1,V4 发送到不同的减速器是没有意义的,因为它们需要放在一起才能被减速。

    试图尽可能简单地解释它

    【讨论】:

    • 如果我们想将 k1,v1 和 k1,v4 发送到同一个 reducer,我们可以做 shuffle。那么排序的目的是什么?
    • 它进行排序有多种原因,一个原因是,当 MapReduce 作业将所有 KV 对发送到减速器时,如果输入未排序,则必须扫描所有 Mapper 输出以拾取 K1,VX 的每个实例。而如果 Mapper 输出在 K2,VX 被拾取后立即排序,则您知道所有 K1,VX 都已被拾取并且该集合可以发送到减速器进行处理,这样做的好处是您不需要必须等待每个 reducer 准备好才能让每个 reducer 开始 reduce。
    • 同样,当涉及到聚合时,如果你指定你想要聚合所有的 K1,V1,如果减速器的输入在减速器接收到 K2,V2 时立即排序,它知道没有存在更多 K1,V1 实例,因此它可以完成聚合,而如果减速器输入未排序,则必须扫描整个输入以查找 K1,V1
    • 我认为原因是这样的:你将键映射到给定的减速器。因此,一次扫描整个键空间就足以将每个 (k,v) 映射到减速器,这样相同的键就会进入相同的分区。完成排序以获得 (k,v1,v2,v3,v4,...) 将在其上运行 reducer 逻辑。这是hadoop的groupby方式
    【解决方案6】:

    混洗是将来自映射器的中间数据传输到 0,1 或更多减速器的过程。每个 reducer 接收 1 个或多个键及其关联值,具体取决于 reducer 的数量(用于平衡负载)。此外,与每个键关联的值在本地排序。

    【讨论】:

      【解决方案7】:

      由于其大小,分布式数据集通常存储在分区中,每个分区包含一组行。这也提高了地图或过滤器等操作的并行性。 shuffle 是对数据集的任何操作,需要在其分区之间重新分配数据。示例包括按键排序和分组。

      对大型数据集进行混洗的常用方法是将执行拆分为 map 和 reduce 阶段。然后数据在 map 和 reduce 任务之间进行混洗。例如,假设我们要对一个有 4 个分区的数据集进行排序,其中每个分区是一组 4 个块。目标是生成另一个有 4 个分区的数据集,但这次是按 key 排序的。

      例如,在排序操作中,每个正方形都是一个排序后的子分区,其键位于不同的范围内。然后每个 reduce 任务对相同阴影的子分区进行合并排序。 上图显示了这个过程。最初,未排序的数据集按颜色(蓝色、紫色、绿色、橙色)分组。洗牌的目标是按阴影(从浅到深)重新组合块。这种重组需要全对多的通信:每个映射任务(一个彩色圆圈)为每个阴影生成一个中间输出(一个正方形),这些中间输出被打乱到它们各自的归约任务(一个灰色圆圈)。

      文字和图片主要取自here

      【讨论】:

        【解决方案8】:

        MapReduce 原生只做两件事:排序和(通过排序实现)可扩展的 GroupBy。

        MapReduce 上的大多数应用程序和设计模式都是基于这两个操作构建的,它们由 shuffle 和 sort 提供。

        【讨论】:

          【解决方案9】:

          This 是一本好书。希望能帮助到你。就您所关心的排序而言,我认为这是 Map 最后一步中的合并操作。当map操作完成后,需要将结果写入本地磁盘时,会对buffer产生的splits进行multi-merge操作。对于合并操作,提前对每个分区进行排序很有帮助。

          【讨论】:

            【解决方案10】:

            嗯, 在 Mapreduce 中有两个重要的短语,分别叫做 Mapperreducer 都太重要了,但是 Reducer 是必须的。在某些程序中,reducers 是可选的。现在来回答你的问题。 洗牌和排序是 Mapreduce 中的两个重要操作。第一个 Hadoop 框架采用结构化/非结构化数据并将数据分离为 Key、Value。

            现在 Mapper 程序将数据分离并排列成要处理的键和值。生成键 2 和值 2 值。该值应按正确顺序处理和重新排列以获得所需的解决方案。现在这个洗牌和排序在您的本地系统中完成(框架负责它)并在流程框架清理本地系统中的数据后在本地系统中处理。 好的

            这里我们也使用 combinerpartition 来优化这个 shuffle 和 sort 过程。经过适当的安排,这些键值传递给 Reducer 以获得所需的 Client 输出。最后 Reducer 得到想要的输出。

            K1, V1 -> K2, V2(我们会写程序Mapper),-> K2, V'(这里是shuffle and soft data) -> K3, V3 生成输出。 K4,V4。

            请注意所有这些步骤只是逻辑操作,不会改变原始数据。

            您的问题:在 Map Reduce 编程中,reducer 中的 shuffle 和 sort 阶段的目的是什么?

            简答:处理数据以获得所需的输出。 shuffle 是聚合数据,reduce 是得到预期的输出。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-04-09
              • 1970-01-01
              • 1970-01-01
              • 2015-04-08
              • 1970-01-01
              • 2015-08-09
              相关资源
              最近更新 更多