1.1 例子,美国 1880 - 2014 年新生婴儿数据统计
- 目标:用美国 1880 - 2014 年新生婴儿的数据来做做简单的统计
- 数据源: https://catalog.data.gov
- 数据格式:
- 每年的新生婴儿数据在一个文件里面
- 每个文件的每一条数据格式:姓名,性别,新生人数
1.2 运行流程概览
上面的 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 的概念:
- 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 会按照执行顺序依次执行。
- 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的划分是以shuffle操作作为边界的。也就是说某个action导致了shuffle,就会划分出两个stage
再次回顾上面那张图:这下应该就明了了,关于两个 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 写下的数据。