spark之RDD

本文详细介绍了Spark中的核心概念RDD,包括其作为只读分区数据集的特性,弹性分布式特性,以及计算、分区和依赖的概念。讨论了RDD的创建、转化和行动操作,如过滤和去重,并介绍了共享变量如广播变量和累加器。还涵盖了RDD的持久化策略和工作流程,强调了DAG图在决定计算过程中的作用。

综述

概念与特性

RDD是spark最重要的抽象。spark统一建立在抽象的RDD之上。设计一个通用的编程抽象,使得spark可以应对各种场合的大数据情景。RDD模型将不同的组件融合到一起,选用其中的几个/所有,可以应付各种不同的场景。解决了mr的缺陷
1. 弹性分布式数据集Resilient Distributed Dataset。
2. 只读分区数据集,final修饰的
3. 一个分布式的数据集合,是spark中的核心,spark的操作都是围绕RDD展开的。
4. 真正的运算是在各个计算节点。
5. 当某个RDD操作丢失的时候,可以很快恢复。

分区

  • 不同分区可能被划分到不同机器上。但是每个分区对应一个数据block
  • 分区是个逻辑概念,新旧分区可能是同一块内存。(重要的优化,节约资源。)。在函数式编程,经常使用常量,但是很费内存,rdd的这种优化非常实用。防止内存的无限性扩充。
  • 只是记录需要做的操作。只有当真正要执行的时候,才具体的执行。

计算

  • 并行计算。计算/处理都是在各分区上,并行计算。并行,提高了效率。
  • 真正的数据处理都是在各个分散的节点上。

依赖

  • 子RDD从父RDD产生,父子RDD之间的关系。
    • 宽依赖:依赖上级所有的RDD分区。宽依赖一般非常消耗资源,结果一般要缓存下来
    • 窄依赖:依赖上级RDD的部分分区。计算的时候可能都在同一个节点上,节省资源
  • stage以依赖的区别,分成不同的stage
  • 每个父RDD的分区,只能被最多一个字RDD使用,子RDD可以使用任意个父RDD。

RDD的操作

创建

  • 从外部数据集中读取。来源于文件系统(HDFS,HBASE),textFile方法
    这里的路径要让每个RDD的节点都能访问到
// 从外部文本中创建RDD。可以指定分片的个数
lines =  sc.textFle("路径",3)
// 一个目录下所有的文件。
lines = sc.wholeTextFile("路径")
// 从hadoop系统创建RDD
val rdd = newApiHadoopFile()
// 从hadoop数据创建RDD
val RDD = new ApiHadoopRDD()
  • 从驱动程序中对一个集合进行并行化
    在测试的时候用的多,parallelize方法。可以指定分区个数
val lines = sc.parallelize(
### Apache SparkRDD 的使用与原理 #### 1. RDD 基本概念 RDD(Resilient Distributed Dataset,弹性分布式数据集)是 Spark 的核心抽象之一。它表示一个不可变的、分区化的集合,可以在集群节点之间分布存储[^3]。RDD 支持两种主要的操作:转换(Transformation)和行动(Action)。这些操作使得开发者能够高效地处理大规模的数据。 #### 2. RDD 特性 以下是 RDD 的一些重要特性: - **只读性**:一旦创建,RDD 数据不能被修改。 - **可分区化**:RDD 可以划分为多个分区,分布在不同的节点上进行并行计算。 - **容错性**:通过记录血缘关系(Lineage),即使某些节点失败,也可以重新计算丢失的部分。 - **持久化支持**:可以选择将 RDD 缓存到内存或磁盘中,从而提高重复使用的效率。 #### 3. RDD 创建方式 RDD 主要可以通过以下几种方式进行创建: - **从外部数据源加载**:例如 HDFS 文件或其他分布式文件系统中的数据。 - **基于已有的 Scala/Python 集合对象**:可以直接将本地集合转化为 RDD。 - **通过对现有 RDD 进行转换**:通过 Transformation 操作生成新的 RDD。 下面是一段简单的代码示例展示如何创建 RDD: ```scala // 导入必要的库 import org.apache.spark.{SparkConf, SparkContext} // 初始化 Spark 上下文 val conf = new SparkConf().setAppName("Example").setMaster("local") val sc = new SparkContext(conf) // 从集合创建 RDD val data = List(1, 2, 3, 4, 5) val rddFromList = sc.parallelize(data) // 从文件创建 RDD val fileRdd = sc.textFile("path/to/file.txt") // 执行 Action 查看结果 rddFromList.collect().foreach(println) fileRdd.foreach(println) ``` 上述代码展示了如何从列表和平面文件分别创建 RDD 并打印其内容[^2]。 #### 4. 转换与行动 ##### 转换(Transformations) 转换是一种返回新 RDD 的懒惰操作。常见的转换包括 `map`、`filter` 和 `reduceByKey` 等。它们不会立即执行,而是构建 DAG 图等待后续触发。 例子如下: ```scala // 使用 map 对每个元素平方 val squaredRdd = rddFromList.map(x => x * x) // 使用 filter 筛选出偶数 val evenNumbers = rddFromList.filter(_ % 2 == 0) ``` ##### 行动(Actions) 行动会触发改写后的实际计算过程,并返回最终结果或者将数据保存至外部存储。典型的行动有 `collect`、`count` 和 `saveAsTextFile`。 例子如下: ```scala // 计算总数量 val countResult = rddFromList.count() // 将结果保存为文本文件 evenNumbers.saveAsTextFile("output/even_numbers") ``` #### 5. 宽依赖与窄依赖 在 Spark 的内部机制中,RDD 的依赖关系决定了 Stage 的划分。如果两个 RDD 存在宽依赖,则意味着需要 shuffle 操作;而窄依赖则不需要 shuffle,因此性能更优[^4]。 #### 6. 总结 RDDSpark 处理大数据的基础组件,具有丰富的特性和强大的灵活性。尽管现代版本逐渐推广 DataFrame 和 DataSet API,但对于底层控制需求较高的场景,RDD 仍然是不可或缺的选择。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值