Spark---RDD依赖关系

22 篇文章 0 订阅
14 篇文章 1 订阅

1.1 RDD依赖关系

在这里插入图片描述
在Spark中,一个RDD的形成依赖于另一个RDD,则称这两个RDD具有依赖关系(一般指相邻的两个RDD之间的关系) ,RDD的依赖关系对于优化Spark应用程序的性能和可靠性非常重要。通过合理地设计RDD的转换和动作操作,可以避免不必要的Shuffle操作,提高计算效率。

    //读取数据
    val lines:RDD[String] = context.textFile("D:\\learnSoftWare\\IdeaProject\\Spark_Demo\\Spark_Core\\src\\main\\com.mao\\datas\\1.txt")
    //执行扁平化操作
    val words : RDD[String] = lines.flatMap((a: String) => a.split(" "))

words的形成依赖于lines,这两个RDD之间就有依赖关系

1.2 血缘关系

依赖关系是对于相邻的两个RDD来说的,如果多个RDD之间存在依赖关系,则称它们之间具有血缘关系。
血缘关系在Spark中起着重要的作用。血缘关系记录了RDD的元数据信息和转换行为,主要用于容错和优化。
由于RDD中是不存储数据的,当计算发生错误的时候,很难重新计算丢失的数据分区。通过记录RDD的血缘关系,Spark可以在数据分区丢失时重新读取数据源并进行计算,从而恢复丢失的数据分区。 这样,即使在处理大规模数据集时,也能保证Spark作业的可靠性和稳定性。
其次,血缘关系还有助于Spark优化查询计划和性能。

    //执行业务操作
    val lines:RDD[String] = context.textFile("D:\\learnSoftWare\\IdeaProject\\Spark_Demo\\Spark_Core\\src\\main\\com.mao\\datas\\1.txt")
    //执行扁平化操作
    //扁平化就是将多个集合打散为一个集合
    val words: RDD[String] = lines.flatMap((a: String) => a.split(" "))

    val wordGroup: RDD[(String, Iterable[String])] = words.groupBy((word: String) => word)
    
    //对分组后的单词进行转换(hello,1)
    val wordToCount: RDD[(String, Int)] = wordGroup.map({
      case (word, list) => {
        (word, list.size)
      }
    })

如上述代码所示,words的形成依赖于lines,wordGroup依赖于words,wordToCount依赖于wordGroup。这些RDD之间就形成了血缘关系。

1.3 依赖关系分类

在Spark中的依赖关系,可以分为窄依赖和宽依赖(也称shuffle依赖)

1.3.1 窄依赖

窄依赖表示每一个父(上游)RDD 的 Partition 最多被子(下游)RDD 的一个 Partition 使用,窄依赖我们形象的比喻为独生子女。

在这里插入图片描述
一个新的分区的数据依赖于一个旧的分区的数据,这样的依赖称之为OneToOne依赖,即窄依赖

1.3.2 宽依赖

宽依赖表示同一个父(上游)RDD 的 Partition 被多个子(下游)RDD 的 Partition 依赖,会引起 Shuffle,总结:宽依赖我们形象的比喻为多生。
在这里插入图片描述
新的分区的数据依赖于多个旧的分区的数据,因为数据会被shuffle,所以宽依赖也被称为shuffle依赖。

1.4 RDD阶段划分和任务划分

1.4.1 RDD阶段划分

RDD(弹性分布式数据集)的阶段划分是在Spark中执行多个RDD时,根据RDD之间的依赖关系进行的。
通过分析各个RDD的依赖关系,可以生成一个依赖图(DAG,有向无环图)。然后,通过分析各个RDD中的分区之间的依赖关系,可以决定如何划分阶段。

Shuffle操作需要在不同的阶段之间进行,因此Spark会根据shuffle依赖关系将数据处理划分为不同的阶段。

DAG(Directed Acyclic Graph)有向无环图是由点和线组成的拓扑图形,该图形具有方向,不会闭环。 例如,DAG 记录了 RDD 的转换过程和任务的阶段。
在这里插入图片描述

具体的划分方法如下:

1.对DAG进行反向解析,遇到宽依赖(ShuffleDependency)就断开,遇到窄依赖就把当前的RDD加入到当前的阶段中。
2.将窄依赖尽量划分在同一个阶段中,这样可以实现流水线计算。
3.一个阶段等于宽依赖(ShuffleDependency)的个数加1。
4.一个阶段中的最后一个RDD的分区个数就是Task的个数。
简而言之,RDD的阶段划分就是在遇到宽依赖时划分出一个新的阶段,每个阶段的任务全部完成,每个分区元素准备就绪后才能进入下一个阶段。

划分出来的阶段的数量=shuffle依赖数量+1

1.4.2 RDD任务划分

RDD 任务切分中间分为:Application、Job、Stage 和 Task
⚫ Application:初始化一个 SparkContext 即生成一个 Application;
⚫ Job:一个 Action 算子就会生成一个 Job;
⚫ Stage:Stage 等于宽依赖(ShuffleDependency)的个数加 1;
⚫ Task:一个 Stage 阶段中,最后一个 RDD 的分区个数就是 Task 的个数。
注意:Application->Job->Stage->Task 每一层都是 1 对 n 的关系。

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值