深入研究 spark 运行原理之 job, stage, task

前言

本文转载自李涛涛的博客

本系列是综合了自己在学习spark过程中的理解记录 + 对参考文章中的一些理解 + 个人实践spark过程中的一些心得而来。写这样一个系列仅仅是为了梳理个人学习spark的笔记记录,所以一切以能够理解为主,没有必要的细节就不会记录了,而且文中有时候会出现英文原版文档,只要不影响理解,都不翻译了。若想深入了解,最好阅读参考文章和官方文档。

其次,本系列是基于目前最新的 spark 1.6.0 系列开始的,spark 目前的更新速度很快,记录一下版本号还是必要的。
最后,如果各位觉得内容有误,欢迎留言备注,所有留言 24 小时内必定回复,非常感谢。

spark 运行原理

这一节是本文的核心,我们可以先抛出一个问题,如果看完这一节,或者这一章之后,你能理解你的整个 spark 应用的执行流程,那就可以关掉这个网页了[对了,关掉网页之前记得分享一下哦,哈哈]

Problem: How does user program get translated into units of physical execution ?

我们用一个例子来说明,结合例子和运行截图来理解。

1.1 例子,美国 1880 - 2014 年新生婴儿数据统计

目标:用美国 1880 - 2014 年新生婴儿的数据来做做简单的统计
数据源https://catalog.data.gov
数据格式:每年的新生婴儿数据在一个文件里面, 每个文件的每一条数据格式:姓名,性别,新生人数
这里写图片描述

  • 代码和结果展示
    这里写图片描述

这里写图片描述

1.2 运行流程概览

还记得我们在 『 Spark 』3. spark 编程模式 讲到的构建一个 spark application 的过程吗:

  • 加载数据集
  • 处理数据
  • 结果展示

上面的 22 行代码,就已经把构建一个 spark app 的三大步骤完成了,amazing, right? 今天我们主要讲 spark 的运行逻辑,所以我们就以核心的 11 - 16 ,这六行代码来作为今天的主线,了解了解 spark 的原理。

这里写图片描述

可以看到,整个逻辑实际上就用了 sparkContext 的一个函数,rdd 的 3 个 transformation 和 1 个 action。
这里写图片描述

现在让我们从 WEB UI 上来看看,当我们运行这段代码的时候,后台都发生了什么。 可以看到,执行这段代码的时候,spark 通过分析,优化代码,知道这段代码需要一个 job 来完成,所以 web ui 上只有一个 job。值得深究的是,这个 job 由两个 stage 完成,这两个 state 一共有 66 个 task。

所以,这里我们就再次理解下 spark 里,job,stage,task 的概念:

所以,这里我们就再次理解下 spark 里,job,stage,task 的概念:

  • 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,简单说一下

Stage 的划分在 RDD 的论文中有详细的介绍,简单的说是以 shuffle 和 result 这两种类型来划分。 在 Spark 中有两类 task:

  • shuffleMapTask

输出是shuffle所需数据, stage的划分也以此为依据,shuffle及之前的所有变换(Transformation)是一个stage,shuffle之后的操作是另一个stage(如果只有一个shuffle)。

  • resultTask

输出是result,比如 rdd.parallize(1 to 10).foreach(println) 这个操作没有shuffle,直接就输出了,那么只有它的task是resultTask,stage也只有一个;如果是rdd.map(x => (x, 1)).reduceByKey(_ + _).foreach(println), 这个job因为有reduce,所以有一个shuffle过程,那么reduceByKey及之前的是一个stage,执行shuffleMapTask,输出shuffle所需的数据,reduceByKey到最后是一个stage,直接就输出结果了。如果job中有多次shuffle,那么每个shuffle之前都是一个stage。

这里就涉及到了shuffle的概念,这里按我的想法描述一下:

Shuffle到底是什么?

Shuffle其实就是指:一套数据被N个嵌套的函数处理(也就是你的transform算子)。遇到了Shuffle,就被切开来,所谓的Shuffle,本质上是把数据按规则临时都落到磁盘上,相当于完成了一个saveAsTextFile的动作,不过是存本地磁盘(非Hdfs)。然后被切开的下一个Stage则以本地磁盘的这些数据作为数据源,重新走上面描述的流程。
我们再做一次描述:
所谓Shuffle不过是把处理流程切分,给切分的上一段(我们称为Stage M)加个存储到磁盘的Action动作,把切分的下一段(Stage M+1)数据源变成Stage M存储的磁盘文件。每个Stage都可以走我上面的描述,让每条数据都可以被N个嵌套的函数处理,最后通过用户指定的动作进行存储或者输出。

  • 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 类似的操作了。]

这里写图片描述

1.3 运行流程之 : job

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

1.4 运行流程之 : stage

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

首先,我们先看看为什么这里会有两个 stage,根据上面对stage的划分描述,目前有两个划分 stage 的标准:

当触发 rdd 的 action 时 : 在我们的应用中就是最后的 collect 操作,关于这个操作的说明,可以看官方文档: rdd.collect
当触发 rdd 的 shuffle 操作时 : 在我们的应用中就是 reduceByKey 这个操作,关于reduceByKey,可以参看本人的博文(非原作者)。
这里写图片描述
再次回顾上面那张图,这下应该就明了了,关于两个 stage 的情况:
这里写图片描述

第一个 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 写下的数据。

1.5 运行流程之 : task

其实到这里应该都理解得差不多了,至于为什么每个 stage 会有 33 个 task [即我们的数据文件存放到 33 个partition 上,可是明明 sc.wholeTextFiles(‘hdfs://10.21.208.21:8020/user/mercury/names’, minPartitions=40) 这里指定了最小要 40 个partition 到啊],这个问题我们留到以后说,在后面我们会有一篇讲怎么调试,优化 spark app 的博文,到时候我们会继续回到这里,解答这里的问题。
这里写图片描述
ps:这两张图可以放大来看,因为shuffle write和shuffle read的时间太短了,可能看不太清楚
这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值