Spark 核心之 Application 和 Job 原理剖析

摘要 :你是否清楚一个 Spark 应用中到底有几个 Job?为什么 .collect() 会触发 Job 而 .map() 不会?Application、Job、Stage、Task 之间的关系到底是什么?本文从四层执行层级全景图、Action 触发 Job 的源码链路、DAGScheduler 的 Stage 切分规则、多 Job 应用实战示例四个维度,配合 1 张原创深色架构图 + 完整源码分析,带你彻底理清 Spark 的执行层级体系。

关键词:Spark Application, Job, Stage, Task, Action, DAGScheduler, SparkContext, 执行层级


一、开篇:你写的一个 Application 到底有几个 Job?

先看一段代码,你能准确说出它会产生几个 Job 吗?

scala 复制代码
val lines = sc.textFile("hdfs:///data/words.txt")     // Transformation
val words = lines.flatMap(_.split(" "))                // Transformation
val pairs = words.map((_, 1))                          // Transformation
val counts = pairs.reduceByKey(_ + _)                  // Transformation

counts.collect()   // Action 1 → Job 0
counts.count()     // Action 2 → Job 1
counts.saveAsTextFile("hdfs:///output")  // Action 3 → Job 2

答案:3 个 Job 。因为每个 Action 算子都会触发一个新的 Job。而 textFile、flatMap、map、reduceByKey 都是 Transformation------它们只是构建 DAG,不触发任何计算。


二、执行层级全景图

2.1 四层模型

scss 复制代码
Application (SparkContext)
  │
  ├── Job-0 (调用 collect() 触发)
  │     ├── Stage 0 (ShuffleMapStage: 2 Tasks)
  │     └── Stage 1 (ResultStage: 3 Tasks)
  │
  ├── Job-1 (调用 count() 触发)
  │     ├── Stage 2 (ShuffleMapStage: 2 Tasks)
  │     └── Stage 3 (ResultStage: 3 Tasks)
  │
  └── Job-2 (调用 saveAsTextFile() 触发)
        ├── Stage 4 (ShuffleMapStage: 2 Tasks)
        └── Stage 5 (ResultStage: 3 Tasks)

三、Action 触发 Job 的源码链路 🔥

scala 复制代码
// 源码:RDD.scala - collect()
def collect(): Array[T] = withScope {
  val results = sc.runJob(this, (iter: Iterator[T]) => iter.toArray)
  results.flatten
}

// 源码:RDD.scala - count()
def count(): Long = sc.runJob(this, Utils.getIteratorSize _).sum

// 源码:RDD.scala - saveAsTextFile()
def saveAsTextFile(path: String): Unit = {
  // ... 内部最终调用 sc.runJob()
}

// 核心链路
// Action → sc.runJob() → DAGScheduler.runJob()
//   → DAGScheduler.handleJobSubmitted()
//   → 创建 ActiveJob → Stage 切分 → submitStage()

3.1 哪些算子是 Action?

算子 返回类型 说明
collect() ArrayT 拉取所有数据到 Driver
count() Long 计数
take(n) ArrayT 取前 n 个
reduce(f) T 聚合
foreach(f) Unit 遍历
saveAsTextFile() Unit 保存到文件
first() T 取第一个

反直觉点 :reduceByKey 不是 Action!它是 Transformation,触发 Shuffle 但不触发 Job。


四、Stage 切分规则

scala 复制代码
// 源码:DAGScheduler.scala
private def getMissingParentStages(stage: Stage): List[Stage] = {
  stage.rdd.dependencies.flatMap {
    case shufDep: ShuffleDependency[_, _, _] =>
      // WideDep → 切分 → 创建父 ShuffleMapStage
      getOrCreateShuffleMapStage(shufDep, stage.firstJobId)
    case _ => Nil  // NarrowDep → 不切分,保持在同一 Stage
  }.toList
}

一句话规则:遇到 ShuffleDependency (Wide Dependency) 即切分 Stage。


五、多 Job 实战示例

scala 复制代码
val rdd = sc.parallelize(1 to 1000, 4)  // 4 Partitions

// Job 1: count
println(s"Count: ${rdd.count()}")       // Action → Job-1
// Job 2: collect
val arr = rdd.collect()                 // Action → Job-2 (无 Shuffle, 1 Stage)
// Job 3: save
rdd.saveAsTextFile("hdfs:///output")    // Action → Job-3

// 总计: 3 个 Job, 3×1=3 个 ResultStage
scala 复制代码
// 带 Shuffle 的场景
val rdd = sc.parallelize(1 to 1000, 4)
  .map(x => (x % 10, x))                // Narrow
  .groupByKey()                          // Wide! Stage 边界

rdd.count()  // Action → Job-1: Stage 0 (ShuffleMapStage) + Stage 1 (ResultStage)

六、Application/Job/Stage/Task 对比表

层级 定义 触发条件 数量
Application SparkContext 实例 spark-submit 1
Job 一个 Action 的完整计算 Action 算子 1~N
Stage Shuffle 边界切分的计算阶段 ShuffleDependency 每个 Job 1~N
Task 处理一个 Partition 的最小单元 Stage 内 Partition 数 每个 Stage 1~N

七、总结

要点 总结
层级关系 1 App = N Jobs = N×M Stages = N×M×P Tasks
Job 触发 每个 Action 算子调用 sc.runJob() 创建新 Job
Stage 切分 遇到 ShuffleDependency 即切分
Task 生成 Stage 最后一个 RDD 的 Partition 数量 = Task 数

金句:Transformation 是"画图纸"(构建 DAG),Action 是"按下启动键"(触发 Job)。一个 Application 可以画无数张图纸,但只有按下的启动键才算数。


作者:starzy | AI Data Engineer / 大数据技术实践者

博客:blog.starzy.cn | GitHub:starzy1990.github.io

专注 AI Agent · LangGraph · RAG · 大数据架构 · 数据工程实践

相关推荐
计算机毕业编程指导师4 小时前
计算机毕设选题推荐:基于Hadoop与Spark的Steam游戏数据分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·python·计算机·spark·毕业设计·steam游戏
计算机毕业编程指导师4 小时前
【计算机毕设选题推荐】基于Hadoop+Spark的白鹿抖音评论大数据分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·python·计算机·spark·毕业设计·抖音评论
计算机毕业编程指导师9 小时前
【大数据毕设选题推荐】基于Spark的WTA职业网球赛事演变与竞技格局分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·计算机·spark·毕业设计·课程设计·wta网球
计算机毕业编程指导师12 小时前
【计算机毕设选题推荐】基于Spark与Hadoop的AI就业收入区域差异分析系统 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·数据分析·spark·毕业设计·课程设计·ai就业收入
计算机毕业编程指导师16 小时前
【大数据毕设选题】基于Spark的电信网络诈骗话术语义特征挖掘分析系统源码 毕业设计 选题推荐 数据分析 机器学习 深度学习
大数据·hadoop·python·spark·毕业设计·课程设计·网络诈骗
计算机毕业编程指导师16 小时前
计算机大数据毕设怎么选?基于Spark的个体肥胖健康风险评估的数据分析与可视化系统带你通关 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·毕业设计·肥胖风险
IT研究室16 小时前
最新大数据毕业设计选题推荐-基于大数据的单位招聘岗位信息分析与可视化-大数据-Spark-Hadoop-Bigdata
大数据·spark·课程设计
计算机毕业编程指导师17 小时前
计算机毕设答辩技巧:基于Hadoop+Django的公共交通运营数据分析与可视化系统怎么做 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·spark·毕业设计·课程设计·交通运行
计算机毕业编程指导师17 小时前
【计算机毕设选题推荐】基于Hadoop+Django高频电力消耗大数据分析系统从0到1 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
hadoop·python·数据分析·spark·毕业设计·课程设计·电力
FYKJ_201017 小时前
springboot手工蜀绣在线销售系统60947-计算机课程设计、毕业设计
java·spring boot·后端·python·mysql·spark·课程设计