Spark中的narrow/wide dependency如何理解,有什么作用?

理由
举报 取消

我在RDD的论文中看到他们的定义是这样的”narrow dependencies, where eachpartition of the parent RDD is used by at most one partitionof the child RDD, wide dependencies, where multiplechild partitions may depend on it”我的理解是narrow就是独生子女,一个父亲只有一个孩子;wide是一个父亲多个孩子。但是我感觉这个定义与论文中区分这两种dependency的作用是矛盾的:“First, narrowdependencies allow for pipelined execution on one clusternode, which can compute all the parent partitions. Forexample, one can apply a map followed by a filter on anelement-by-element basis. In contrast, wide dependenciesrequire data from all parent partitions to be availableand to be shuffled across the nodes using a MapReducelikeoperation. Second, recovery after a node failure ismore efficient with a narrow dependency, as only the lostparent partitions need to be recomputed, and they can berecomputed in parallel on different nodes. In contrast, ina lineage graph with wide dependencies, a single failednode might cause the loss of some partition from all theancestors of an RDD, requiring a complete re-execution.”narrow的第一个作用,我的理解是可以不用等上一次操作全部做完,每完成一条记录就可以进行下次操作,如map产生一条新纪录马上就做filter,但是对于wide,为什么不能这样做呢?另外,union是narrow操作,对两个分区做合并不需要shuffle吗,为什么只有wide操作才需要shuffle?对于narrow的第二个作用,两种dependency丢失单个分区会分别导致哪些其他分区也丢失呢?

2018年2月15日 6 条回复 1447 次浏览

发起人:张楠 初入职场

在线教育创业者

回复 ( 6 )

  1. 用心阁
    理由
    举报 取消

    如图:

    (图片来源:

    我们知道RDD就是一个不可变的带分区的记录集合,Spark提供了RDD上的两类操作,转换和动作。转换是用来定义一个新的RDD,包括map, flatMap, filter, union, sample, join, groupByKey, cogroup, ReduceByKey, cros, sortByKey, mapValues等,动作是返回一个结果,包括collect, reduce, count, save, lookupKey。

    首先要注意一点,就是分区,那么:

    1. 如果一个RDD的依赖的每个分区只依赖另一个RDD的同一个分区,就是narow,如图上的C和D,D和F,B和G,这样就不需要进行shuffle,同时还可以按照流水线的方式,把一个分区上的多个操作放在一个Task里进行,如图上覆盖C,D,F的红色阴影。
    2. 如果一个RDD的每个分区需要依赖另一个RDD的所有分区,就是wide,如图上的A和B,F和G,这样的依赖需要进行shuffle,需要更多的运算。

    参见: 与 Hadoop 对比,如何看待 Spark 技术? – 用心阁的回答

  2. 匿名用户
    理由
    举报 取消

    楼上答案很好。。。我想能解答楼主疑问了。。。我是来讨论的。。。

    如果把wide split的定义改为child partition depends on multiple parents which are not guaranteed to exist on the same node的话,解释就变得非常简单了——multiple parents的数据必须shuffle到同一个node上才可以算child。。。这是楼上说的2号情况。。。我一向也是这么理解的。。。

    不过感谢题主把原论文中关于这个概念的原话贴出来,给了我一个重新思考这个问题的机会。。。

    我发现真的很神奇哦。。。spark真的是按照论文里那么设计的而不是按照我以往的理解。。。

    试想,如果我们搞一个localSplit的操作,把一个partition分成同一个node上的多个partitions. 这是一个multiple children depend on one parent的wide dependency情况,但是正如题主说的,好像也没有什么不可以的。。。反正数据都在同一个node上,想怎么搞还不是随便。。。

    然而spark就真的没这类transformation!!!真的没有。。。coalesce只能减少partition数。。。repartition用的是shuffle的办法。。。。凡是可能改变partition数的transformation(除了coalesce)貌似都需要shuffle。。。

    当然可以想象对一个partition执行某个计算得到的结果不容易同时存入两个不同的partitions, 也可以理解localSplit这类操作好像也不是非常有意义,但是依然觉得这是一个可以解决的问题。。。

    这个设定究竟是出于某些我没想到的固有限制,还是仅仅是spark就想这么设计?没想明白。。。

    @用心阁能解答一下吗。。。

  3. Reid Chan
    理由
    举报 取消

    其中一个作用 可用于区分stage 方便stage内优化

    其二 真的就是数据行为特点 需要多依赖

  4. Angryrou
    理由
    举报 取消

    楼上有人画了Stage的划分,但是似乎没有正对性地回答楼主的问题。

    在这里说一下我的理解,希望可以和大家讨论。

    0. 首先,关于楼主的例子。

    “独生子女”、“父亲”的概念应该对应的都是RDD里的partition的概念。那么narrow dependency 的理解,根据论文里的定义应该是,每个父亲至多只有一个孩子,此时,也可以是多个父亲对应一个孩子。而wide dependency里,多个孩子会依赖同一个父亲,也就是child RDD里的partition会依赖于parent(s)RDD里的多个partitions

    我之前从集合映射的概念去理解。如果从parent RDD里的partition 到child RDD的partition是一对一或者多对一的,就是narrow dependency;若为多对多或者一对多的,则是wide dependency

    1. 关于楼主的第一个问题,举个例子:

    val rdd1 = rdd0.map(...).filter(...).collect() 
    val rdd2 = rdd0.map(...).groupByKey(...).collect()
    
  5. dog ameng
    理由
    举报 取消

    我的疑问和题主一样,包括为什么宽依赖不能流水线 (pipeline)优化?

    比如cogroup是一个字分区有有限个父分区,多个依赖的数据不还是要fetch过来

  6. 用户头像
    理由
    举报 取消

    @用心阁 已经给出了专业答案。

    按楼主自己粗糙的说法,“narrow就是独生子女,一个父亲只有一个孩子;wide是一个父亲多个孩子”,wide更像是多个父亲一(多)个孩子….O(∩_∩)O哈哈~

我来回答

Captcha 点击图片更换验证码