『 Spark 』6. 深入研究 spark 运行原理之 job, stage, task

写在前面

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

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

Tips: 如果插图看起来不明显,可以:1. 放大网页;2. 新标签中打开图片,查看原图哦;3. 点击右边目录上方的 present mode 哦。

1. spark 运行原理

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

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

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

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

baby-data-format.jpg

### packages
import pandas as pd

### spark UDF (User Defined Functions)
def map_extract(element):
    file_path, content = element
    year = file_path[-8:-4]
    return [(year, i) for i in content.split("\r\n") if i]

### spark logic
res = sc.wholeTextFiles('hdfs://10.21.208.21:8020/user/mercury/names', 
                        minPartitions=40)  \
        .map(map_extract) \
        .flatMap(lambda x: x) \
        .map(lambda x: (x[0], int(x[1].split(',')[2]))) \
        .reduceByKey(operator.add) \
        .collect()

### result displaying
data = pd.DataFrame.from_records(res, columns=['year', 'birth'])\
         .sort(columns=['year'], ascending=True)
ax = data.plot(x=['year'], y=['birth'], 
                figsize=(20, 6), 
                title='US Baby Birth Data from 1897 to 2014', 
                linewidth=3)
ax.set_axis_bgcolor('white')
ax.grid(color='gray', alpha=0.2, axis='y')

baby-name-1.jpg

1.2 运行流程概览

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

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

baby-name-2.jpg

可以看到,整个逻辑实际上就用了 sparkContext 的一个函数,rdd 的 3 个 transformation 和 1 个 action。

baby-name-job.jpg

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

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

baby-name-ui-1.jpg

1.3 运行流程之 : job

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

baby-name-3.jpg

1.4 运行流程之 : stage

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

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

baby-name-4.jpg

再次回顾上面那张图:

baby-name-job.jpg

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

baby-name-5.jpg

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 的博文,到时候我们会继续回到这里,解答这里的问题。

baby-name-7.jpg baby-name-8.jpg baby-name-9.jpg baby-name-10.jpg baby-name-11.jpg baby-name-12.jpg

2. Next

既然我们都慢慢开始深入理解 spark 的执行原理了,那下次我们就来说说 spark 的一些配置吧,然后再说说 spark 应用的优化。

7. 打开微信,扫一扫,点一点,棒棒的,^_^

wechat_pay_6-6.png

参考文章

本系列文章链接