基于本文回答

播面 播面

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

Spark Transformation(转换)算子和 Action(行动)算子的区别是什么?

知识点图片

在 Apache Spark 中,Transformation(转换)算子和 Action(行动)算子是 RDD(弹性分布式数据集)操作的两大核心类别。

它们最本质的区别在于:Transformation 是“惰性”(Lazy)的,只记录逻辑不执行;而 Action 是“触发器”,它会真正启动计算任务。

以下是详细的对比分析:

1. 核心定义与行为区别

特性 Transformation (转换算子) Action (行动算子)
返回值 返回一个新的 RDD 返回 非 RDD 的结果(如 Int, Array, Map)或无返回值(写入文件)。
执行模式 惰性求值 (Lazy Evaluation)。不会立即触发计算。 立即执行。触发 Spark 提交 Job 并开始计算。
作用 构建逻辑执行计划(DAG/血统)。 触发物理执行,将结果返回给 Driver 或写入外部存储。
数量关系 一个 Spark 应用中可以有无限个 Transformation。 一个 Action 对应一个 Job。没有 Action,Spark 程序什么都不做。

2. 详细原理解析

Transformation (转换算子)

  • 功能:将一个已存在的 RDD 转换成一个新的 RDD。
  • 原理:当你调用 mapfilter 时,Spark 并没有真正去处理数据。它只是在内部记录下了一个操作步骤(构建 DAG 有向无环图),记住了“如果将来要计算数据,需要先做 A,再做 B”。这被称为建立 RDD 的 Lineage(血统)
  • 分类
    • Narrow (窄依赖):父 RDD 的一个分区只被子 RDD 的一个分区使用(无 Shuffle)。例如:map, filter, flatMap.
    • Wide (宽依赖):父 RDD 的一个分区被子 RDD 的多个分区使用(涉及 Shuffle)。例如:groupByKey, reduceByKey, join.

Action (行动算子)

  • 功能:触发计算,处理数据,并产生最终结果。
  • 原理:当代码运行到 Action 算子时,Spark Context 会查看之前积累的所有 Transformation 逻辑(DAG),制定物理执行计划,向集群提交一个 Job,真正开始读取数据、计算并输出。
  • 数据流向:结果数据要么被拉取回 Driver 端(如 collect),要么被写入 外部存储系统(如 HDFS, S3)。

3. 常见算子举例

常用的 Transformation

  • map(func): 元素一对一映射。
  • filter(func): 过滤数据。
  • flatMap(func): 一对多映射。
  • groupByKey(): 按 Key 分组。
  • reduceByKey(func): 按 Key 聚合。
  • union(otherRDD): 合并两个 RDD。
  • distinct(): 去重。

常用的 Action

  • collect(): 将所有数据拉取回 Driver(注意内存溢出风险)。
  • count(): 返回数据集的元素个数。
  • first(): 返回第一个元素。
  • take(n): 返回前 n 个元素。
  • saveAsTextFile(path): 保存到文件系统。
  • foreach(func): 对每个元素执行操作(通常用于写入数据库)。
  • reduce(func): 聚合所有元素返回一个值(注意与 reduceByKey 的区别)。

4. 为什么要设计成“惰性求值”?

Spark 之所以将 Transformation 设计为 Lazy,主要是为了 性能优化

  1. 流水线优化 (Pipelining):如果 Spark 立即执行每一步,那么 map 之后可能需要把中间结果写内存,然后 filter 再读出来。通过惰性求值,Spark 可以将多个窄依赖操作(如 map + filter)合并在同一个 Stage 中,数据读进来后直接处理并过滤,减少内存/磁盘 IO。
  2. 只计算需要的数据:如果你写了 rdd.map(...).filter(...).take(1),因为 Action 是 take(1),Spark 知道只需要一个结果,它可能在找到第一个符合条件的数据后就停止计算整个数据集,而不是处理完几 TB 数据后再给你第一条。

5. 生活类比

想象你在餐厅点餐:

  1. Transformation (写菜单)

    • 你说:“我要一份牛排”(rdd1
    • 你说:“牛排要七分熟”(rdd2 = rdd1.map
    • 你说:“再加点黑胡椒”(rdd3 = rdd2.map
    • 此时厨师并没有开始做菜,服务员只是在纸上记下了你的要求。
  2. Action (下单/上菜)

    • 你说:“好了,下单吧/上菜吧”(rdd3.collect()
    • 此时厨师才真正开始切肉、煎肉、撒调料,最后把成品端给你。

总结

  • Transformation = 定义逻辑(返回 RDD,不干活)。
  • Action = 执行逻辑(返回结果,开始干活)。
00:00
00:00