Spark --【宽依赖和窄依赖】

原创
2019/04/10 17:32
阅读数 512

1.前言

《上一节Spark DAG概述》Spark中RDD的高效与DAG图有着莫大的关系,在DAG调度中需要对计算过程划分stage,
暴力的理解就是stage的划分是按照有没有涉及到shuffle来划分的,没涉及的shuffle的都划分在一个stage里面,
这种划分依据就是RDD之间的依赖关系。针对不同的转换函数,RDD之间的依赖关系分类窄依赖(narrow dependency)
和宽依赖(wide dependency, 也称 shuffle dependency)

2.定义

1.窄依赖是指父RDD的每个分区只被子RDD的一个分区所使用,子RDD分区通常对应常数个父RDD分区(O(1),与数据规模无关)
2.相应的,宽依赖是指父RDD的每个分区都可能被多个子RDD分区所使用,子RDD分区通常对应所有的父RDD分区(O(n),与数据规模有关)
3.宽依赖和窄依赖关系图:
     

3.为什么要有宽窄依赖?

1.前面已经说过了stage划分的一个很重要的原因就是有没有涉及到shuffle,如果没涉及到的被划分到一个stage里面。
2.没有涉及shuffle的任务直接运行就可以,这个也就是常提到的pipeline。这种面向的就是窄依赖。
    √ 每个分区里的数据都被加载到机器的内存里,我们逐一的调用 map, filter, map 函数到这些分区里,Job 就很好的完成。
    √ 更重要的是,由于数据没有转移到别的机器,我们避免了 Network IO 或者 Disk IO. 
    唯一的任务就是把 map / filter 的运行环境搬到这些机器上运行,这对现代计算机来说,overhead 几乎可以忽略不计。
    √ 这种把多个操作合并到一起,在数据上一口气运行的方法在 Spark 里叫 pipeline 
    (其实 pipeline 被广泛应用的很多领域,比如 CPU)。
    这时候不同就出现了:只有 narrow transformation 才可以进行 pipleline 操作。
    对于 wide transformation, RDD 转换需要很多分区运算,包括数据在机器间搬动,所以失去了 pipeline 的前提。
    √ 总结起来一句话:数据和算是否在一起,计算的性能是不一样的,为了区分,就有了宽依赖和窄依赖。
3.一提到shuffle如果之前对mapreduce有过了解的人都知道,这个对分布式影响巨大,
spark也是一步步演变过来的,现在可以说spark2.x以上的shuffle可以认为和经典的mapreduce的shuffle一样了,到现在可以
说spark完全比mr有优势了。这之前,在一些场景下spark还是比不过mr的。(看这篇《Spark 与MapReduce 资源调度方面的简单对比》)

4.宽窄依赖如何优化?----得想想

4.窄依赖对优化的帮助

1.宽依赖往往对应着shuffle操作,需要在运行过程中将同一个父RDD的分区传入到不同的子RDD分区中,中间可能涉及到多个节点之间的
  数据传输;而窄依赖的每个父RDD的分区只会传入到一个子RDD分区中,通常可以在一个节点内就可以完成了。
2.当RDD分区丢失时(某个节点故障),spark会对数据进行重算。
    1).对于窄依赖,由于父RDD的一个分区只对应一个子RDD分区,这样只需要重算和子RDD分区对应的父RDD分区即可,
    所以这个重算对数据的利用率是100%的;
	2).对于宽依赖,重算的父RDD分区对应多个子RDD分区,这样实际上父RDD 中只有一部分的数据是被用于恢复这个丢失的子RDD
    分区的,另一部分对应子RDD的其它未丢失分区,这就造成了多余的计算;更一般的,宽依赖中子RDD分区通常来自多个父RDD
    分区,极端情况下,所有的父RDD分区都要进行重新计算。 
3.如下图所示,b1分区丢失,则需要重新计算a1,a2和a3,这就产生了冗余计算(a1,a2,a3中对应b2的数据)
    
区分这两种依赖很有用。首先,窄依赖允许在一个集群节点上以流水线的方式(pipeline)计算所有父分区。
例如,逐个元素地执行map、然后filter操作;
而宽依赖则需要首先计算好所有父分区数据,然后在节点之间进行Shuffle,这与MapReduce类似。
第二,窄依赖能够更有效地进行失效节点的恢复,即只需重新计算丢失RDD分区的父分区,而且不同节点之间可以并行计算;
而对于一个宽依赖关系的Lineage图,单个节点失效可能导致这个RDD的所有祖先丢失部分分区,因而需要整体重新计算。

窄依赖中每个子RDD可能对应多个父RDD,当子RDD丢失时会导致多个父RDD进行重新计算,所以窄依赖不如宽依赖有优势。

而实际上应该深入到分区级别去看待这个问题,而且重算的效用也不在于算的多少,而在于有多少是冗余的计算。
窄依赖中需要重算的都是必须的,所以重算不冗余

窄依赖的函数有:map, filter, union, join(父RDD是hash-partitioned ), mapPartitions, mapValues 
宽依赖的函数有:groupByKey, join(父RDD不是hash-partitioned ), partitionBy
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部