Spark RDD之Dependency

概要

上一篇我们介绍了代表RDD组成的(Dependency、Partition、Partitioner)之一的Partition,这篇接着介绍Dependency。
Partition记录的是数据split的逻辑,Dependency记录的是transformation操作过程中Partition的演化,即这个Partition从哪来到哪去的过程,以及通过Dependency的类型判断如何处理数据,即pipeline还是shuffle。

Dependency定义

在这里插入图片描述
我的另一篇博客RDD 运行原理中介绍了RDD的组成,及Dependency的分类以及缘由,这里不再累述,先看下Dependency的定义:
在这里插入图片描述
Dependency是抽象类,有一个属性rdd,就是对应RDD的父RDD,所以Dependency就是对父RDD的包装,并且通过Dependency的类型说明当前这个transformation对应的数据处理方式,其主要子类实现,即Dependency的类型有两大类:

1. NarrowDependency(窄依赖)

在这里插入图片描述
窄依赖依然是抽象类,继承了rdd,并在定义中增加抽象方法getParents,根据子RDD的PartitionId返回对应的父RDD的PartitionId,接下来查看窄依赖的具体实现:

  • OneToOneDependency
    在这里插入图片描述
    OneToOneDependency表示子RDD和父RDD的Partition之间的关系是1对1的,即子RDD的PartitionId和父RDD的PartitionId一样,如第一幅图中,Narrow Dependency下面的map和filter方法所示的关系。

  • RangeDependency
    在这里插入图片描述
    RangeDependency表示子RDD和父RDD的Partition之间的关系是一个区间内的1对1对应关系,第一幅图中所示Narrow Dependency下面的union就是RangeDependency

  • PruneDependency
    在这里插入图片描述
    子RDD的Partition来自父RDD的多个Partition,filterByRange方法时会使用,不做详细讨论

2. ShuffleDependency(宽依赖)

在这里插入图片描述
ShuffleDependency的定义相对复杂一些,因为shuffle涉及到网络传输,所以要有序列化serializer,为了减少网络传输,可以加map端聚合,通过mapSideCombine和aggregator控制,还有key排序相关的keyOrdering,以及重输出的数据如何分区的partitioner,其他信息包括k,v和combiner的class信息以及shuffleId。shuffle是个相对复杂且开销大的过程,Partition之间的关系在shuffle处戛然而止,因此shuffle是划分stage的依据。

Dependency分为两大类,宽依赖和窄依赖,窄依赖有两个主要实现。

举个例子

以Wordcount为例

	val wordcount = sc.parallelize(List("a c", "a b"))
	wordcount.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).collect()

通过web UI查看DAG,如下:
在这里插入图片描述
可以看出,其根据shuffle的位置划分为两个stage,stage0和stage1
调用toDebugString查看各RDD之间关系
在这里插入图片描述
最后,总结出Wordcount中RDD及其对应的Dependency如下,其中方形代表RDD,圆角矩形代表Partition(3个圆角矩形是为了作图方便,不代表其具体有3个Partition),文本框内第一行为代码片段,第二行是对应的RDD,第三行为RDD的Dependency类型

在这里插入图片描述
总结
Dependency是RDD的重要组成,分为宽依赖和窄依赖两大类,实质就是其父RDD的包装,由Dependency组成的关系构成了lineage的物理结构,也是DAG的物理结构,宽依赖(即shuffle操作)是stage划分的依据,窄依赖可以执行流水线(pipeline)操作,效率高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark RDD(弹性分布式数据集)的依赖机制是Spark实现容错性和高效计算的核心机制之一。 在Spark中,每个RDD都表示一个可分区、只读的数据集。RDD之间的依赖关系描述了RDD之间的转换操作,并指示了RDD如何通过转换操作从父RDD生成新的子RDDRDD的依赖关系可以分为两种类型:窄依赖(Narrow Dependency)和宽依赖(Wide Dependency)。 1. 窄依赖:当一个父RDD的每个分区只被一个子RDD的一个分区所使用时,我们称之为窄依赖。在这种情况下,Spark可以高效地进行转换操作,而无需重新计算所有的数据。例如,map、filter等转换操作都属于窄依赖。窄依赖允许Spark在计算中进行更多的优化,如任务划分、数据本地性等。 2. 宽依赖:当一个父RDD的分区被多个子RDD的分区所使用时,我们称之为宽依赖。在这种情况下,Spark需要通过将数据进行洗牌(Shuffle)操作来重新组织数据,以满足子RDD的需求。例如,groupByKey、reduceByKey等转换操作都属于宽依赖。洗牌操作需要涉及数据的网络传输和排序,因此会引入额外的开销。 Spark使用DAG(有向无环图)来表示RDD之间的依赖关系。每个RDD都包含其对应的转换操作和所依赖的父RDD。当执行一个Action操作时,Spark会根据RDD之间的依赖关系动态构建执行计划,并将其转化为一系列的任务来执行。 通过依赖机制,Spark可以实现容错性,即当某个分区的数据丢失或计算失败时,可以通过依赖关系重新计算该分区的数据。同时,Spark还可以根据依赖关系进行任务划分和数据本地化等优化,以提高计算效率和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值