SparkCore 之 Spark Action 类算子详解

简介: 本文系统拆解Spark全部Action算子,按输出、存储、聚合、统计四类详解语法、原理、数据流向与OOM陷阱;含原创架构图、Scala示例及排错指南,助Java/大数据/AI工程师安全高效使用。(239字)

摘要:系统拆解 Spark 全部 Action 算子——按输出类、存储类、聚合类、统计类四大分类,逐个剖析语法、底层原理、Driver/Executor 数据流向和性能陷阱。配有 2 张原创架构图、完整 Scala 代码示例和常见 OOM 排查指南。面向 Java、大数据及 AI 开发工程师。


一、Action vs Transformation — 本质区别

Action(行动算子)是 Spark 中触发计算的唯一入口。所有 Transformation 只构建 DAG,Action 才是真正按下"执行按钮"的那个操作。

维度 Transformation Action
返回值 新 RDD 非 RDD(值/数组/写入存储)
触发计算 ❌ 不触发 ✅ 触发 DAG 执行
DAGScheduler 不参与 触发 Stage 划分 + Task 提交
执行时机 惰性求值 立即触发
代表 map / filter / join count / collect / saveAsTextFile

二、输出类 Action — 将数据拉回 Driver

2.1 collect — 收集全部数据到 Driver

// 签名:def collect(): Array[T]
// ⚠️ 所有数据通过网络传输到 Driver 内存
// 数据量大时 → Driver OOM!

val rdd = sc.parallelize(1 to 1000)
rdd.collect()  // Array[Int](1,2,...,1000) — 全部在Driver内存中

// ❌ 危险用法:PB 级数据 collect
sc.textFile("hdfs://100TB-logs/").collect()  // Driver OOM 必现!

// ✅ 正确用法:数据量小(<几MB)时才用 collect
rdd.filter(_.contains("specific_keyword")).collect()  // 过滤后数据量小

2.2 take — 取前 N 条

// 签名:def take(num: Int): Array[T]
// 只拉指定数量到 Driver,不会 OOM

rdd.take(10)    // 前10条
rdd.take(100)   // 前100条

// take 的底层执行:
// 先取第一个 Partition → 不够再取第二个 → 直到凑满 num 条
// 性能优于 collect(尤其数据量大时)

2.3 foreach / foreachPartition — 遍历执行(不返回Driver)

// foreachPartition: 每个分区执行一次(推荐!)
rdd.foreachPartition { iter =>
  val conn = DriverManager.getConnection(url)  // 每个分区创建1次连接
  iter.foreach { record =>
    conn.execute(s"INSERT INTO t VALUES ($record)")
  }
  conn.close()
}
// mapPartitions + foreachPartition 组合是写入外部系统的最优模式

三、存储类 Action — 将数据写入外部存储

3.1 saveAsTextFile — 写入文本文件

// 签名:def saveAsTextFile(path: String)
// 每个 Partition 写入一个文件(part-00000, part-00001, ...)

rdd.saveAsTextFile("hdfs://output/result/")

// ⚠️ 目标目录不能已存在(否则抛异常)
// 解决方案:先删除目录
val path = new Path("hdfs://output/result/")
path.getFileSystem(sc.hadoopConfiguration).delete(path, true)
rdd.saveAsTextFile("hdfs://output/result/")

四、聚合类 Action — 在 Executor 聚合后返回 Driver

4.1 reduce — 全局聚合

// 签名:def reduce(f: (T, T) => T): T
// 先在每个分区内聚合 → Shuffle → 最终聚合 → 返回Driver

val rdd = sc.parallelize(1 to 100)
rdd.reduce(_ + _)        // 5050
rdd.reduce(_ max _)      // 100

// ⚠️ reduce 要求函数满足结合律和交换律

4.2 aggregate — 灵活的分区内/区间聚合

// 求平均值
val rdd = sc.parallelize(1 to 100)
val (sum, count) = rdd.aggregate((0, 0))(
  seqOp  = { case ((s, c), v) => (s + v, c + 1) },
  combOp = { case ((s1, c1), (s2, c2)) => (s1 + s2, c1 + c2) }
)
val avg = sum.toDouble / count  // 50.5

4.3 treeAggregate / treeReduce — 树形聚合(推荐)

// 树形聚合避免单点 OOM
rdd.treeReduce(_ + _, depth = 3)       // 推荐用于大数据集
rdd.treeAggregate(zero)(seqOp, combOp, depth = 3)

五、统计类 Action — 便捷统计函数

rdd.count()                    // 计数
rdd.countByKey()               // 按Key统计 → Map[K, Long] (⚠️ OOM)
rdd.max()                      // 最大值
rdd.min()                      // 最小值
rdd.sum()                      // 求和
rdd.histogram(10)              // 直方图
rdd.toDebugString              // 查看Lineage

六、Action 算子速查表

算子 分类 返回 数据流向 OOM 风险
collect() 输出 Array[T] →Driver ⚠️ 高
take(n) 输出 Array[T] →Driver ✅ 低
foreachPartition 输出 Unit →Executor ✅ 无
saveAsTextFile 存储 Unit →磁盘 ✅ 无
reduce(f) 聚合 T →Driver ✅ 低
aggregate 聚合 U →Driver ✅ 低
treeReduce 聚合 T →Driver ✅ 极低
count() 统计 Long →Driver ✅ 极低
countByKey() 统计 Map →Driver ⚠️ 高

七、常见 Action 陷阱与排查

陷阱 现象 解决
collect OOM OutOfMemoryError take(n) 替代
countByKey OOM Driver GC overhead reduceByKey(_+_).collect()
foreach 打印不显示 输出在Executor日志 collect().foreach(println)
saveAsTextFile 目录已存在 FileAlreadyExistsException 先删除目录

写在最后

Action 算子虽然数量不多(约 20 个),但理解它们的数据流向和内存压力至关重要:

  • collect/countByKey → Driver:数据向 Driver 汇聚 → 控制数据量
  • foreach/saveAsTextFile → Executor/存储:数据向外发散 → 无内存压力
  • reduce/aggregate → 聚合后返回:Executor 间聚合 → 关注 Shuffle

选对 Action,不仅决定性能,更决定你的 Driver 会不会 OOM。

目录
相关文章
|
22天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
9215 29
|
21天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
4527 16
|
8天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
20天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2401 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
7天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
567 1
|
2天前
|
存储 缓存 测试技术
QWT 3D 模块重构记:旧渲染管线改进介绍及实时瀑布图示例
QWT 3D模块完成重大重构:解耦窗口与图形(Plot+Item),摒弃OpenGL 1.x固定管线,迁至Core Profile着色器渲染;支持多图元同场景叠加,并以实时3D瀑布图验证——滑动窗口、固定色域、64帧×256点达61fps。兼容Qt 5.12+/6,LGPL协议。
151 120
|
9天前
|
人工智能 Linux Windows
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
千问办公(QwenWork)是阿里云推出的AI智能办公平台,支持网页端直接使用及Windows/Mac/Linux客户端下载。提供PPT生成、财报分析、网页搭建等AI功能,个人版免费,企业版198元/席/月。详情见官网qwenwork.cn或阿里云产品页。
1126 0
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
|
14天前
|
Windows
【保姆级】.NET Framework 3.5离线安装教程(2026最新实测)
.NET Framework 3.5是微软经典运行库,专为兼容老软件、老游戏设计。Win7自带,Win10/11需手动启用(在线或离线安装)。它与4.x系列并存不冲突,缺它会导致“找不到组件”报错。本文详解两种安装方式及常见问题解决,小白也能轻松上手。(239字)
1667 0
|
3天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型全解析:核心原理拆解,性能实战测评与落地部署教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为System One Model(系统一模型),对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
341 0

热门文章

最新文章