【问题标题】:In SPARK, why Narrow Dependency strictly doesn't require schuffle over the network?在 SPARK 中,为什么 Narrow Dependency 严格不需要通过网络进行混洗?
【发布时间】:2018-10-14 03:13:03
【问题描述】:

我正在阅读关于跨多个分区的 RDD 的 Narrow Vs Wide dependencies

我的问题:我不明白为什么用 Narrow Dependencies 构建的 RDD 不需要通过网络进行混洗?还是 shuffle 确实发生了,但只发生了几次?

请参考下图-

假设一个子 RDD 是从父 RDD 创建的,具有 Narrow Dependency,如下面的红色矩形所示。现在,父 RDD 有 3 个分区,比方说 (P1,P2,P3),每个分区中的数据被映射到分别映射到 3 个其他分区,比方说 (P1,P4,P5)。

由于父 RDD 分区 P1 中的数据被映射到自身,因此网络上没有 shuffle。但是由于来自父 RDD 分区 P2 和 P3 的数据被映射到子 RDD 分区 P4 和 P5,它们是不同的分区,所以数据自然必须通过网络在 P4 和 P5 中放置相应的值。因此,为什么我们说网络上没有洗牌?

见绿色方框,这是更复杂的情况。只有当父 RDD 分区映射到自身时,我才能看到网络上没有随机播放的情况。

我确信我的推理是不正确的。有人可以提供一些解释吗? 谢谢

【问题讨论】:

  • 我的理解有缺陷。发生的情况是,当我们在 RDD 上应用 map() 函数时,分区不会改变。最多,分区器/散列将被破坏。因此,跨 3 个分区 (P1,P2,P3) 的父 RDD 将导致子 RDD 分别精确地分布在 (P1,P2,P3) 上,每个分区数据使用 map(function) 一对一映射。因此,上面的红框中不会有洗牌。
  • 在绿框中,由于两个父RDD具有相同的分区器(它们是共同分区的),因此具有相同键的数据将位于同一分区上,因此不涉及洗牌。因此,只有 join() 操作会导致窄依赖,其中两个 RDD 都使用相同的分区器进行分区,否则 join() 操作将导致宽依赖,这意味着跨网络的数据混洗。
  • 注意:在上面的绿色框中。不是 6 个分区,而是 3 个,因为输入的 RDD 是共同分区的,即;使用相同的分区器进行分区,从而导致具有相同键的元素以相同的分区索引结尾。如果 RDD1 放置在 (P1,P2,P3) 上,则 RDD2 也同样放置在 (P1,P2,P3) 上。仅仅因为有 6 个盒子并不意味着 6 个分区;)

标签: apache-spark networking dependencies rdd partitioning


【解决方案1】:

让我打个比方来说明分区。 如果你有一组文档,想要过滤它以识别所有未正确填写的文档,这相当于进行了一次过滤操作。为了加快操作,您将这组文档分发给三个人,因此每个人都有一个文档分区。然后每个人筛选给他们的文档子集(在输入框中),并将未正确填写的文档放入输出框中。 每个人执行的操作使得输出框的内容仅取决于提供给他们的输入框;别人的输入框与输出无关。因此不需要网络传输。

希望这能解释清楚。

【讨论】:

    【解决方案2】:

    从您提供的链接:

    一个典型的执行顺序如下... RDD最初是从外部数据源创建的(例如HDFS、Local file...等) RDD经过一系列的TRANSFORMATION(例如map、flatMap、filter、groupBy、join) ,每个都提供一个不同的 RDD,用于下一个转换。最后最后一步是一个ACTION(例如count、collect、save、take),它将最后一个RDD转换为输出到外部数据源上面的处理顺序称为lineage(DAG的拓扑排序的结果)

    现在想想数据在通过管道时是如何处理的。

    如果存在窄依赖,则子分区仅依赖于 1 个父分区。父分区的数据可以在一台机器上处理,然后子分区可以存在于同一台机器上。无需对数据进行混洗。

    如果存在广泛的依赖关系,则 1 个子分区依赖于许多父分区。父分区可能存在于多台机器上,因此数据必须经过网络shuffle才能完成数据处理。

    【讨论】:

    • 好吧,从本质上讲,您的答案 - 每次构建 RDD 以执行某些“动作”时,DAG 都会直接针对原始外部数据源执行。我对吗?是的,如果一切都是一对一的,比如在红色矩形中,那么我完全可以理解数据将在本地计算并保留在同一个分区中。现在,请看绿色标记的矩形。在这里,来自 6 个分区的数据被合并为 3 个,因此必须有跨网络的移动/洗牌/流量,尽管有手推车依赖性,这种洗牌仍在发生。请让我知道我的逻辑缺陷。谢谢!!
    • 有些混乱的好地方。作为记录,我会说绿框产生了广泛的依赖性。但是,它不一定需要洗牌。这是因为要加入的 RDD 中的任何 ID 的数据都存在于同一台机器上。至少这就是共同分区的含义。而且由于给定键的所有数据都在一台机器上,因此不需要对数据进行混洗来进行连接。这可以通过使用partitionBybucketBy 来完成(但这些转换需要随机播放)
    • 我会说绿色框会产生广泛的依赖关系 - 根据the original paper 的定义,它不会。这是 1:1。
    • Each partition of the parent RDD is used by at most one partition of the child RDD 你是对的。我一直在向后考虑它(例如,子分区仅依赖于 1 个父分区,而不是 1 个父分区最多产生 1 个子分区)。绿色的盒子很窄。不过,其余的评论应该没问题。
    • 谢谢@David。非常感谢您的意见。
    【解决方案3】:

    窄依赖并不意味着没有网络流量。

    窄和宽的区别更微妙:

    • 具有广泛依赖关系的每个子分区都依赖于其父分区的每个分区。这是多对多的关系。
    • 对于窄依赖,每个子分区最多依赖于每个父分区的一个分区。它可以是一对一或多对一的关系。

    是否需要网络流量取决于转换以外的其他因素。例如,如果在同一操作期间发生 shuffle(在这种情况下同时存在 co-partitioning 和 co-location),则可以在没有网络流量的情况下加入 co-partitioned RDD,否则可以加入网络流量。

    【讨论】:

    • 原谅我的无知,我知道我在玩一个可怜的知识基金,但是网络流量和网络洗牌之间有区别吗?我认为网络洗牌意味着将数据从分区移动到另一个分区,任何洗牌都相当于流量,还是我大错特错?
    • @OliverS Shuffle 需要网络流量,但并不是 Spark 中的每一个网络流量都与 shuffle 相关(而且,shuffle 比网络流量还多)。
    • 是的,你确实是对的。每次洗牌都会增加流量,但每次流量都不是洗牌的结果。非常感谢@user9613318 的宝贵意见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2015-09-03
    • 2011-02-23
    • 1970-01-01
    • 2017-11-17
    • 1970-01-01
    相关资源
    最近更新 更多