RDD的依赖关系?

 

RDD和它依赖的parent RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)宽依赖(wide dependency)

1)窄依赖指的是每一个parent RDD的Partition最多被子RDD的一个Partition使用,如图1所示。

2)宽依赖指的是多个子RDD的Partition会依赖同一个parent RDD的Partition,如图2所示。

  RDD作为数据结构,本质上是一个只读的分区记录集合。一个RDD可以包含多个分区,每个分区就是一个dataset片段。RDD可以相互依赖。

  1)如果RDD的每个分区最多只能被一个Child RDD的一个分区使用,则称之为narrow dependency。

  2)如果多个Child RDD分区都可以依赖,则称之为wide / shuffle dependency 。

Spark之所以将依赖分为narrow 和 shuffle / wide 。基于两点原因

  1、首先,narrow dependencies可以支持在同一个cluster node上,以pipeline形式执行多条命令,例如在执行了map后,紧接着执行filter。

    相反,shuffle / wide dependencies 需要所有的父分区都是可用的,可能还需要调用类似MapReduce之类的操作进行跨节点传递。

2、其次,则是从失败恢复的角度考虑。 narrow dependencies的失败恢复更有效,因为它只需要重新计算丢失的parent partition即可,而且可以并行地在不同节点进行重计算。

       相反,shuffle / wide dependencies 牵涉RDD各级的多个parent partition。

                    

        图 1  RDD的窄依赖                  图 2 RDD的宽依赖

接下来可以从不同类型的转换来进一步理解RDD的窄依赖和宽依赖的区别,如图3所示。

 对于map和filter形式的转换来说,它们只是将Partition的数据根据转换的规则进行转化,并不涉及其他的处理,可以简单地认为只是将数据从一个形式转换到另一个形式。对于union,只是将多个RDD合并成一个,parent RDD的Partition(s)不会有任何的变化,可以认为只是把parent RDD的Partition(s)简单进行复制与合并。对于join,如果每个Partition仅仅和已知的、特定的Partition进行join,那么这个依赖关系也是窄依赖。对于这种有规则的数据的join,并不会引入昂贵的Shuffle。对于窄依赖,由于RDD每个Partition依赖固定数量的parent RDD(s)的Partition(s),因此可以通过一个计算任务来处理这些Partition,并且这些Partition相互独立,这些计算任务也就可以并行执行了。

   对于groupByKey,子RDD的所有Partition(s)会依赖于parent RDD的所有Partition(s),子RDD的Partition是parent RDD的所有Partition Shuffle的结果,因此这两个RDD是不能通过一个计算任务来完成的。同样,对于需要parent RDD的所有Partition进行join的转换,也是需要Shuffle,这类join的依赖就是宽依赖而不是前面提到的窄依赖了。

  不同的操作依据其特性,可能会产生不同的依赖。例如map、filter操作会产生 narrow dependency 。reduceBykey操作会产生 wide / shuffle dependency。

  通俗点来说,RDD的每个Partition,仅仅依赖于父RDD中的一个Partition,这才是窄。 就这么简单!

   反正子Rdd的partition和父Rdd的Partition如果是一对一就是窄依赖,这样理解就好区分了 !!!

 
 

     我以前总感觉这是窄依赖,其实 Rdd1的partition0依赖父Rdd0的 partition0和partition1,所以是宽依赖

所有的依赖都要实现trait Dependency[T]:

abstract class Dependency[T] extends Serializable {
    def rdd: RDD[T]
}
 
其中rdd就是依赖的parent RDD。
 
 
对于窄依赖的实现是:
 
abstract class NarrowDependency[T](_rdd: RDD[T]) extends Dependency[T] {
    //返回子RDD的partitionId依赖的所有的parent RDD的Partition(s)
    def getParents(partitionId: Int): Seq[Int]
    override def rdd: RDD[T] = _rdd
}
 
现在有两种窄依赖的具体实现,一种是一对一的依赖,即OneToOneDependency:
 
class OneToOneDependency[T](rdd: RDD[T]) extends NarrowDependency[T](rdd) {
    override def getParents(partitionId: Int) = List(partitionId)
 
 
 
 
 
    通过getParents的实现不难看出,RDD仅仅依赖于parent RDD相同ID的Partition。
还有一个是范围的依赖,即RangeDependency,它仅仅被org.apache.spark.rdd.UnionRDD使用。UnionRDD是把多个RDD合成一个RDD,这些RDD是被拼接而成,即每个parent RDD的Partition的相对顺序不会变,只不过每个parent RDD在UnionRDD中的Partition的起始位置不同。因此它的getPartents如下:
override def getParents(partitionId: Int) = {
    if(partitionId >= outStart && partitionId < outStart + length) {
       List(partitionId - outStart + inStart)
    } else {
       Nil
    }
}

其中,inStart是parent RDD中Partition的起始位置,outStart是在UnionRDD中的起始位置,length就是parent RDD中Partition的数量。

对于宽依赖的实现是:

  宽依赖的实现只有一种:ShuffleDependency。子RDD依赖于parent RDD的所有Partition,因此需要Shuffle过程:

class ShuffleDependency[K, V, C](
    @transient _rdd: RDD[_ <: Product2[K, V]],
    val partitioner: Partitioner,
    val serializer: Option[Serializer] = None,
    val keyOrdering: Option[Ordering[K]] = None,
    val aggregator: Option[Aggregator[K, V, C]] = None,
    val mapSideCombine: Boolean = false)
extends Dependency[Product2[K, V]] {
 
override def rdd = _rdd.asInstanceOf[RDD[Product2[K, V]]]
//获取新的shuffleId
val shuffleId: Int = _rdd.context.newShuffleId()
//向ShuffleManager注册Shuffle的信息
val shuffleHandle: ShuffleHandle =
_rdd.context.env.shuffleManager.registerShuffle(
    shuffleId, _rdd.partitions.size, this)
 
    _rdd.sparkContext.cleaner.foreach(_.registerShuffleForCleanup(this))
}
  宽依赖支持两种Shuffle Manager,即org.apache.spark.shuffle.hash.HashShuffleManager(基于Hash的Shuffle机制)和org.apache.spark.shuffle.sort.SortShuffleManager(基于排序的Shuffle机制)。
 

Spark RDD概念学习系列之RDD的依赖关系(宽依赖和窄依赖)(三)的更多相关文章

  1. Spark RDD概念学习系列之rdd的依赖关系彻底解密(十九)

    本期内容: 1.RDD依赖关系的本质内幕 2.依赖关系下的数据流视图 3.经典的RDD依赖关系解析 4.RDD依赖关系源码内幕 1.RDD依赖关系的本质内幕 由于RDD是粗粒度的操作数据集,每个Tra ...

  2. Spark RDD概念学习系列之RDD的转换(十)

    RDD的转换 Spark会根据用户提交的计算逻辑中的RDD的转换和动作来生成RDD之间的依赖关系,同时这个计算链也就生成了逻辑上的DAG.接下来以“Word Count”为例,详细描述这个DAG生成的 ...

  3. Spark RDD概念学习系列之RDD的checkpoint(九)

     RDD的检查点 首先,要清楚.为什么spark要引入检查点机制?引入RDD的检查点?  答:如果缓存丢失了,则需要重新计算.如果计算特别复杂或者计算耗时特别多,那么缓存丢失对于整个Job的影响是不容 ...

  4. Spark RDD概念学习系列之RDD的5大特点(五)

      RDD的5大特点  1)有一个分片列表,就是能被切分,和Hadoop一样,能够切分的数据才能并行计算. 一组分片(partition),即数据集的基本组成单位,对于RDD来说,每个分片都会被一个计 ...

  5. Spark RDD概念学习系列之RDD是什么?(四)

       RDD是什么? 通俗地理解,RDD可以被抽象地理解为一个大的数组(Array),但是这个数组是分布在集群上的.详细见  Spark的数据存储 Spark的核心数据模型是RDD,但RDD是个抽象类 ...

  6. Spark RDD概念学习系列之RDD的容错机制(十七)

    RDD的容错机制 RDD实现了基于Lineage的容错机制.RDD的转换关系,构成了compute chain,可以把这个compute chain认为是RDD之间演化的Lineage.在部分计算结果 ...

  7. Spark RDD概念学习系列之RDD的缓存(八)

      RDD的缓存 RDD的缓存和RDD的checkpoint的区别 缓存是在计算结束后,直接将计算结果通过用户定义的存储级别(存储级别定义了缓存存储的介质,现在支持内存.本地文件系统和Tachyon) ...

  8. Spark RDD概念学习系列之RDD的操作(七)

    RDD的操作 RDD支持两种操作:转换和动作. 1)转换,即从现有的数据集创建一个新的数据集. 2)动作,即在数据集上进行计算后,返回一个值给Driver程序. 例如,map就是一种转换,它将数据集每 ...

  9. Spark RDD概念学习系列之RDD的缺点(二)

        RDD的缺点? RDD是Spark最基本也是最根本的数据抽象,它具备像MapReduce等数据流模型的容错性,并且允许开发人员在大型集群上执行基于内存的计算. 为了有效地实现容错,(详细见ht ...

随机推荐

  1. leetcode:Plus One

    Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...

  2. C++关键字 inline

    在C&C++中 一.inline关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中表达式形式的宏定义. 表达式形式的宏定义一例: #define ExpressionName(Va ...

  3. 无锁编程(五) - RCU(Read-Copy-Update)

    RCU(Read-Copy Update) RCU就是指读-拷贝修改,它是基于其原理命名的.对于被RCU保护的共享数据结构,读操作不需要获得任何锁就可以访问,但写操作在访问它时首先拷贝一个副本,然后对 ...

  4. Codeforces Round #276 (Div. 2)

    A. Factory 题意:给出a,m,第一天的总量为a,需要生产为a%m,第二天的总量为a+a%m,需要生产(a+a%m)%m 计算到哪一天a%m==0为止 自己做的时候,把i开到1000来循环就过 ...

  5. HDU 5384 Danganronpa (Trie树)

    题意:给出两个集合S和T,集合中每个元素是个字符串,而T集合中任一元素都是个子弹,可以打S中的任一怪物,如果子弹是怪物的子串,那么才有伤害值1,若在怪物中出现多次,次数为该子弹打到该怪物的伤害值.每个 ...

  6. HDU2102 A计划

    解题思路:一道简单题,却WA了十几发,犯几个低级错误.还是不能急躁,     内心要平静,具体分析见代码: #include<iostream> #include<cstdio> ...

  7. type tips

    网上有这么一篇文章,全文如下:http://bbs.9ria.com/blog-220191-18429.html AS3中一共有以下六种获取变量类型的方法:   typeof  instanceof ...

  8. 剑指offer—第三章高质量的代码(按顺序打印从1到n位十进制数)

    题目:输入一个数字n,按照顺序打印出1到最大n位十进制数,比如输入3,则打印出1,2,3直到最大的3位数999为止. 本题陷阱:没有考虑到大数的问题. 本题解题思路:将要打印的数字,看成字符串,不足位 ...

  9. 类 .xml

    pre{ line-height:1; color:#1e1e1e; background-color:#d2d2d2; font-size:16px;}.sysFunc{color:#627cf6; ...

  10. 【LeetCode】228 - Summary Ranges

    Given a sorted integer array without duplicates, return the summary of its ranges. For example, give ...