Spark RDD之Dependency

本文深入解析了Spark中RDD的Dependency概念,包括其分类——窄依赖和宽依赖,并通过Wordcount实例展示了不同类型的Dependency如何影响数据处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

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

Dependency定义

 
我的另一篇博客Spark RDD中介绍了RDD的组成,及Dependency的分类以及缘由,这里不再累述,先看下Dependency的定义: 

Dependency是抽象类,有一个属性rdd,就是对应RDD的父RDD,所以Dependency就是对父RDD的包装,并且通过Dependency的类型说明当前这个transformation对应的数据处理方式,其主要子类实现,即Dependency的类型有两大类:

  • NarrowDependency(窄依赖) 

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

      OneToOneDependency表示子RDD和父RDD的Partition之间的关系是1对1的,即子RDD的PartitionId和父RDD的PartitionId一样,如第一幅图中,Narrow Dependency下面的map和filter方法所示的关系。
    2. RangeDependency 
      RangeDependency表示子RDD和父RDD的Partition之间的关系是一个区间内的1对1对应关系,第一幅图中所示Narrow Dependency下面的union就是RangeDependency
    3. PruneDependency 
      子RDD的Partition来自父RDD的多个Partition,filterByRange方法时会使用,不做详细讨论
  • 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)操作,效率高。

### 如何通过 IDEA 连接 Spark RDD 并进行数据处理 在大数据领域,Apache Spark 提供了一种高效的方式来进行分布式数据处理[^1]。为了实现基于 Scala 的 Spark 开发环境搭建以及 RDD 操作,可以通过 Maven 配置项目依赖并编写相应的代码来完成。 以下是关于如何通过 IntelliJ IDEA (简称 IDEA) 来连接 Apache Spark 并执行 RDD 数据处理的具体说明: #### 一、Maven 配置 要设置一个能够运行 Spark 应用程序的开发环境,需先配置项目的 `pom.xml` 文件中的 Maven 依赖项。以下是一个典型的 Maven 配置示例用于支持 Spark Streaming 和 Kafka 的集成[^2]: ```xml <dependencies> <!-- Spark Core --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>2.4.0</version> </dependency> <!-- Spark SQL --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.4.0</version> </dependency> <!-- Optional: If you need streaming functionality --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming_2.11</artifactId> <version>2.4.0</version> </dependency> </dependencies> ``` 上述配置包含了 Spark 核心库 (`spark-core`) 和 Spark SQL 功能的支持。如果需要其他模块(如流式处理),也可以按需添加对应的依赖。 --- #### 二、Spark RDD 基本操作示例 RDD(Resilient Distributed Dataset)是 Spark 中的核心抽象之一,表示不可变的数据集合。下面展示了一个简单的例子,演示如何加载本地文件到 RDD 并对其进行基本转换和动作操作。 ##### 示例代码:读取文本文件并对单词计数 ```scala import org.apache.spark.{SparkConf, SparkContext} object WordCountExample { def main(args: Array[String]): Unit = { val conf = new SparkConf() .setAppName("Word Count Example") // 设置应用程序名称 .setMaster("local[*]") // 使用本地模式运行(适用于测试) val sc = new SparkContext(conf) try { // 加载本地文件为 RDD val textFile = sc.textFile("input.txt") // 对每行分割成单词,并统计每个单词出现次数 val wordCounts = textFile.flatMap(line => line.split("\\s+")) .map(word => (word, 1)) .reduceByKey(_ + _) // 输出结果 wordCounts.collect().foreach(println) } finally { sc.stop() // 关闭 Spark 上下文 } } } ``` 在此代码片段中: - **`textFile.flatMap(...)`** 将每一行拆分为单独的单词; - **`map(...)`** 创建键值对 `(word, 1)` 表示每个单词及其初始计数值; - **`reduceByKey(...)`** 合并具有相同 key 的值以得到最终的词频统计结果。 --- #### 三、多列分区优化 对于大型数据集,在实际应用中可能还需要考虑性能调优问题。例如,可以利用 `partitionBy()` 方法按照某些特定字段重新分配数据分布,从而提高后续计算效率[^4]。 假设我们有一个包含用户行为记录的日志表结构如下所示: | userId | actionType | timestamp | |--------|------------|-----------| | u1 | click | t1 | | u2 | purchase | t2 | 那么可以根据业务需求选择合适的维度进行分片调整。比如按 `userId` 列创建哈希分区或者范围分区等策略均可有效减少 shuffle 成本。 --- ### 总结 以上介绍了如何借助 IDE 工具构建适合于 Spark 开发的工作空间,并给出了针对 RDD 数据模型的一些基础实践案例。希望这些内容能帮助理解其工作原理及应用场景价值所在!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值