Spark入门知识(application, job, stage, task)

本文详细解析了Spark的执行模型,包括job、stage和task的概念及其运行流程。通过实例分析,阐述了job触发机制,stage划分标准,以及task执行单元的角色。文章还探讨了Spark如何通过调度器分配任务,以及在不同阶段如何处理数据分区。

http://litaotao.github.io/deep-into-spark-exection-model

1.what这个技术是什么

官方文档定义 

spark 里,job,stage,task 的概念:

  • application(应用):其实就是用spark-submit提交的程序
  • job : A job is triggered by an action, like count() or saveAsTextFile(). Click on a job to see information about the stages of tasks inside it. 理解了吗,所谓一个 job,就是由一个 rdd 的 action 触发的动作,可以简单的理解为,当你需要执行一个 rdd 的 action 的时候,会生成一个 job。
  • stage : stage 是一个 job 的组成单位,就是说,一个 job 会被切分成 1 个或 1 个以上的 stage,然后各个 stage 会按照执行顺序依次执行。至于 job 根据什么标准来切分 stage,可以回顾第二篇博文:『 Spark 』2. spark 基本概念解析 
  • task : A unit of work within a stage, corresponding to one RDD partition。即 stage 下的一个任务执行单元,一般来说,一个 rdd 有多少个 partition,就会有多少个 task,因为每一个 task 只是处理一个 partition 上的数据。从 web ui 截图上我们可以看到,这个 job 一共有 2 个 stage,66 个 task,平均下来每个 stage 有 33 个 task,相当于每个 stage 的数据都有 33 个 partition [注意:这里是平均下来的哦,并不都是每个 stage 有 33 个 task,有时候也会有一个 stage 多,另外一个 stage 少的情况,就看你有没有在不同的 stage 进行 repartition 类似的操作了。]

 

2.why为什么有这个技术

此技术解决什么问题

  1. 提交application,构建Spark Application的运行环境,启动SparkContext
  2. SparkContext向资源管理器(可以是Standalone,Mesos,Yarn)申请运行Executor资源,并启动StandaloneExecutorbackend,
  3. Executor向SparkContext申请Task
  4. SparkContext将应用程序分发给Executor
  5. SparkContext构建成DAG图,将DAG图分解成Stage、将Taskset发送给Task Scheduler,最后由Task Scheduler将Task发送给Executor运行
  6. Task在Executor上运行,运行完释放所有资源

 

3.how怎么学这个技术

运行流程之 : job

根据上面的截图和再次重温,我们知道这个 spark 应用里只有一个 job,那就是因为我们执行了一个 collect 操作,即把处理后的数据全部返回到我们的 driver 上,进行后续的画图,返回的数据如下图:

baby-name-3.jpg

 

job数不等于stage数例子每个action操作是一个job。而每一个宽依赖将会产生一个stage):http://blog.sina.com.cn/s/blog_6dd718930102xgm3.html

我们这个 spark 应用,生成了一个 job,这个 job 由 2 个 stage 组成,并且每个 stage 都有 33 个task,说明每个 stage 的数据都在 33 个 partition 上,这下我们就来看看,这两个 stage 的情况。

首先,我们先看看为什么这里会有两个 stage,根据 『 Spark 』2. spark 基本概念解析  中对 stage 的描述,目前有两个划分 stage 的标准:

  • 当触发 rdd 的 action 时 : 在我们的应用中就是最后的 collect 操作,关于这个操作的说明,可以看官方文档: rdd.collect
  • 当触发 rdd 的 shuffle 操作时 (宽依赖往往对应着shuffle操作,需要在运行过程中将同一个父RDD的分区传入到不同的子RDD分区中): 在我们的应用中就是 reduceByKey 这个操作,官方文档: rdd.reduceByKey

baby-name-4.jpg

再次回顾上面那张图:

 

这下应该就明了了,关于两个 stage 的情况:

baby-name-5.jpg

  • 第一个 stage,即截图中 stage id 为 0 的 stage,其执行了 sc.wholeTextFiles().map().flatMap().map().reduceByKey() 这几个步骤,因为这是一个 Shuffle 操作,所以后面会有 Shuffle Read 和 Shuffle Write。具体来说,就是在 stage 0 这个 stage 中,发生了一个 Shuffle 操作,这个操作读入 22.5 MB 的数据,生成 41.7 KB 的数据,并把生成的数据写在了硬盘上。

  • 第二个 stage,即截图中 stage id 为 1 到 stage,其执行了 collect() 这个操作,因为这是一个 action 操作,并且它上一步是一个 Shuffle 操作,且没有后续操作,所以这里 collect() 这个操作被独立成一个 stage 了。这里它把上一个 Shuffle 写下的数据读取进来,然后一起返回到 driver 端,所以这里可以看到他的 Shuffle Read 这里刚好读取了上一个 stage 写下的数据。

其实到这里应该都理解得差不多了,至于为什么每个 stage 会有 33 个 task [即我们的数据文件存放到 33 个partition 上。

<think>好的,用户想了解Spark中的JobStageTask的划分概念。首先,我需要回忆一下Spark的基本执行模型。根据之前的引用资料,特别是引用[3],里面提到Application包含多个Job,每个Job由动作操作触发。接下来,Job会被分解成Stage,而Stage又由Task组成。 用户可能已经知道一些基本概念,但需要更详细的解释。需要分层次来讲解,从ApplicationJob,再到StageTask。要确保每个概念的定义清晰,并且说明它们之间的关系。 记得引用[1]提到DAGScheduler将DAG划分为Stage,划分的依据是计算因子的输入是否确定,也就是是否有宽依赖。这里需要解释宽窄依赖的区别,因为这是Stage划分的关键。 另外,引用[3]指出Job对应动作操作,比如count或collect。所以每个动作操作生成一个Job,这点很重要。用户可能想知道为什么会有多个Job,这里需要举例说明,比如多次调用不同的动作操作。 关于Stage,需要解释为什么会有Shuffle Map Stage和Result Stage,以及它们的作用。Task部分要说明每个Stage分成多个TaskTask是实际执行的最小单元,分布在集群的Executor上。 可能还需要提到资源分配,引用[1]中TaskScheduler申请资源,提交Task到Worker节点执行。这里可以说明Task的数量由分区数决定,分区数影响并行度。 用户的问题可能与性能优化相关,比如Stage划分如何影响执行效率,避免资源开销。引用[1]提到避免多个Stage之间的消息传递开销,所以需要强调宽依赖导致Stage划分,而窄依赖可以合并Stage,优化执行流程。 最后,生成相关问题时要考虑用户可能的后续疑问,比如如何查看这些划分,优化方法,或者具体例子。确保问题覆盖概念理解、实际应用和优化策略。</think>### JobStageTaskSpark 中的划分概念 在 Spark 分布式计算框架中,**JobStageTask** 是执行层次的核心概念,用于组织和管理计算任务的执行流程。以下是它们的定义与划分逻辑: --- #### 一、Job(作业) 1. **定义** - 一个 Job 表示由用户通过**动作操作**(如 `collect()`, `count()`, `save()` 等)触发的完整计算任务。 - 每个 Spark 应用程序(Application)可以包含多个 Job,每个 Job 对应一次独立的计算过程[^3]。 2. **触发条件** - 例如:执行 `rdd.count()` 时,Spark 会生成一个 Job 来计算 RDD 中的元素总数。 3. **执行流程** - Job 会生成一个**有向无环图(DAG)**,描述 RDD 之间的依赖关系(窄依赖或宽依赖)[^1]。 --- #### 二、Stage(阶段) 1. **定义** - StageJob 的**逻辑执行单元**,由 DAGScheduler 根据 RDD 的**宽依赖(Shuffle Dependency)** 划分而来[^1]。 - 每个 Job 会被拆分为多个 Stage,分为两种类型: - **Shuffle Map Stage**:负责为 Shuffle 准备数据(如 `groupByKey` 前的 `map` 操作)。 - **Result Stage**:直接生成最终结果(如 `reduce` 操作)。 2. **划分依据** - 宽依赖(如 `groupByKey`, `join`)会导致 Stage 的划分,因为需要跨节点数据交换(Shuffle); - 窄依赖(如 `map`, `filter`)则会被合并到同一个 Stage 中[^1]。 3. **示例** - 若一个 Job 包含 `map → filter → groupByKey → reduce`,则会在 `groupByKey` 前划分为两个 Stage。 --- #### 三、Task(任务) 1. **定义** - TaskStage 的**物理执行单元**,对应一个分区(Partition)上的计算操作。 - 每个 Stage 会根据分区数量生成多个 Task,并行执行[^3]。 2. **类型** - **Shuffle Map Task**:属于 Shuffle Map Stage,输出数据供后续 Stage 使用。 - **Result Task**:属于 Result Stage,直接输出最终结果。 3. **执行过程** - TaskScheduler 将 Task 分配到集群的 Worker 节点上,由 Executor 执行[^1]。 - 例如:若一个 Stage 有 100 个分区,则会生成 100 个 Task,每个 Task 处理一个分区的数据。 --- #### 四、层级关系总结 | 层级 | 触发条件 | 划分依据 | 物理/逻辑 | 数量关系 | |----------|------------------|---------------------|------------|------------------------------| | Job | 动作操作 | 用户代码中的动作 | 逻辑单元 | 1个 Application → N个 Job | | Stage | 宽依赖(Shuffle)| DAG 的依赖关系 | 逻辑划分 | 1个 Job → M个 Stage | | Task | 分区数量 | 数据分布与并行度 | 物理执行 | 1个 Stage → K个 Task(=分区数) | --- #### 五、示例场景 假设有以下代码: ```python rdd = sc.parallelize(data, 4) # 4个分区 rdd.map(f1).filter(f2).groupByKey().count() ``` 执行流程: 1. `count()` 触发一个 Job。 2. DAGScheduler 将 Job 划分为两个 Stage: - Stage 1:`map(f1) → filter(f2)`(窄依赖,合并为一个 Stage)。 - Stage 2:`groupByKey → count`(宽依赖导致 Stage 划分)。 3. Stage 1 生成 4 个 Shuffle Map TaskStage 2 生成 4 个 Result Task。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值