基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

spark的rdd是什么?

RDD(Resilient Distributed Dataset,弹性分布式数据集)是 Apache Spark 的核心概念。它是 Spark 最基本的数据抽象,代表一个不可变、可分区、里面的元素可并行计算的集合

理解 RDD 可以拆解为以下三个关键词:

  1. Resilient(弹性):页意味着容错性。如果某个节点上的数据丢失或损坏,Spark 可以根据其“血统(Lineage)”重新计算生成该数据,而不需要像传统 MapReduce 那样进行昂贵的磁盘备份。
  2. Distributed(分布式):数据被分成多个分区(Partitions),分散存储在集群的不同节点上,从而可以进行并行计算
  3. Dataset(数据集):它就像一个只读的记录集合,可以存放各种类型的数据(如 Java 对象、Python 对象、文本、键值对等)。

一、 RDD 的五大核心特性

在 Spark 内部,每一个 RDD 都可以用五个核心属性来表示:

  1. 分区列表(A list of partitions):一个 RDD 被分成多个分区,每个分区都在集群的一个节点上运行。分区是 Spark 并行计算的最小单位。
  2. 计算每个分裂的函数(A function for computing each split):Spark 会将计算逻辑(算子)发送给每个分区执行。
  3. 对其他 RDD 的依赖列表(A list of dependencies on other RDDs):RDD 之间存在依赖关系(称为血统 Lineage)。这是 RDD 能够容错的关键。
  4. 键值对 RDD 的分区器(An optional Partitioner for key-value RDDs):决定了数据如何分发到不同的分区中(例如:HashPartitioner、RangePartitioner)。
  5. 首选位置列表(An optional list of preferred locations):存储每个分区的最佳计算节点位置(实现“数据不动,代码动”的本地化计算,提高效率)。

二、 RDD 的核心操作(两类算子)

Spark 对 RDD 的操作分为两类:Transformation(转换算子)Action(行动算子)

1. Transformation(转换)

转换算子负责将一个 RDD 转换为另一个新的 RDD

  • 特点惰性求值(Lazy Evaluation)。这意味着当你调用转换算子时,Spark 并不会立即执行计算,而只是记录下这个转换操作(构建 DAG 图)。
  • 常用算子map(), filter(), flatMap(), reduceByKey(), groupByKey(), distinct() 等。

2. Action(行动)

行动算子会触发真正的计算,并将结果返回给 Driver 程序或保存到外部存储系统(如 HDFS)。

  • 特点:一旦调用 Action 算子,Spark 就会提交作业(Job),开始真正的分布式计算。
  • 常用算子collect(), count(), first(), take(n), reduce(), saveAsTextFile() 等。

三、 RDD 的容错机制:Lineage(血统)

这是 RDD “弹性”的来源。

  • RDD 是不可变(Immutable)的。每次转换都会生成一个新的 RDD,从而形成一个链条,称为 Lineage(血统/依赖链)
  • 如果某个节点宕机,导致该节点上的 RDD 分区数据丢失,Spark 不需要从头开始重新计算,也不需要读取备份。它只需要根据 Lineage 找到这个分区是由父 RDD 的哪个分区转换来的,仅重新计算丢失的这部分数据

依赖关系分为两类:

  • 窄依赖(Narrow Dependency):父 RDD 的每个分区最多被一个子 RDD 分区使用(如 map, filter)。这种情况下,丢失数据只需局部重算,效率极高。
  • 宽依赖(Wide Dependency,即 Shuffle):父 RDD 的一个分区会被多个子 RDD 分区使用(如 groupByKey, reduceByKey)。这种情况下会发生数据网络传输(Shuffle),容错恢复成本较高。

四、 代码示例(以 PySpark 为例)

以下是一个经典 Word Count(单词计数)的例子:

python
# 1. 创建 RDD (从外部文件读取)
text_rdd = sc.textFile("hdfs://path/to/file.txt")

# 2. Transformation 操作 (此时不进行实际计算)
words_rdd = text_rdd.flatMap(lambda line: line.split(" "))  # 切分单词
pairs_rdd = words_rdd.map(lambda word: (word, 1))          # 转换为 (word, 1) 键值对
word_counts_rdd = pairs_rdd.reduceByKey(lambda a, b: a + b) # 局部及全局聚合

# 3. Action 操作 (触发实际计算,并将结果保存)
word_counts_rdd.saveAsTextFile("hdfs://path/to/output")

五、 RDD 的局限性与现代 Spark 的演变

虽然 RDD 是 Spark 的基石,但在现代 Spark 开发中,直接使用 RDD 的场景已经变少。

RDD 的缺点:

  1. 缺乏结构化信息:RDD 只知道数据是一个个对象,但不知道对象内部有哪些字段、类型是什么。
  2. 没有自动优化:用户写什么代码,Spark 就怎么执行,无法像 SQL 那样进行自动查询优化。

演变:
因此,Spark 2.x/3.x 引入了更高层级的 API:DataFrameDataset

  • DataFrame/Dataset 在 RDD 的基础上加入了 Schema(表结构)
  • 它们底层使用 Catalyst 优化器Tungsten 执行引擎,能够自动优化代码,性能远超直接编写 RDD。

总结RDD 是 Spark 的底层灵魂。尽管现在推荐使用 DataFrame/Dataset 进行业务开发,但理解 RDD 的分区、容错、Lazy 机制和 Shuffle,对于深入理解 Spark 的底层原理和性能调优至关重要。

00:00
00:00