spark中job、stage和task之间的关系

job:应用程序中的每个acion操作(如collect、count、saves、reduce)都会创建成一个job,一个job由多个stage和task组成。与action操作相对应的是transformations操作(如map、reduceByKey),transformations从旧的RDD中生成新的RDD(如大小写转换、字段过滤)
以下是官方手册对action和transformation的解释

RDDs support two types of operations: transformations, which create a new dataset from an existing one, and actions, which return a value to the driver program after running a computation on the dataset. For example, map is a transformation that passes each dataset element through a function and returns a new RDD representing the results. On the other hand, reduce is an action that aggregates all the elements of the RDD using some function and returns the final result to the driver program (although there is also a parallel reduceByKey that returns a distributed dataset).

stage:每个作业可以在单个stage或多个stage中执行,这取决于操作的复杂性,例如当需要有必要的数据混排时,一个job会有多个stage。
task:task时从驱动进程发送给执行进程的工作单元。每个task会在RDD的每个分区上执行,因此,如果RDD有10个分区,则一个stage会产生10个一样的task。使用HDFS做为数据源时RDD默认取决于原始文件在HDFS中的分区数量。

下面从代码层面来看一下这三者之间的关系。

from pyspark import SparkContext, SparkConf

conf = SparkConf().setAppName("yarnTest")
sc = SparkContext(conf=conf)
text_file = sc.textFile("/LICENSE")
wordText = text_file.flatMap(lambda line:line.split(" "))
UpperWord=wordText.map(lambda word:word.upper())
wordCount = UpperWord.map(lambda word:(word,1)).reduceByKey(lambda x,y:x+y)
print(wordCount.collect())

上述代码对一个对文本进行一些简单操作的spark-Python代码。

第三行 初始化应用配置,设定应用名称为"yarnTest"
第四行 使用配置创建一个SparkContext
第五行 从HDFS中读取一个文本文件创建RDD
第六行 使用空格分隔单词,并生成新的RDD,新的RDD每行一个单词。对应了一个transformations操作
第七行 将所有的单词装换为大写,对应一个transformations操作
第八行 统计每个单词的数量,其中reduceByKey会触发一次数据混排(shuffle)生成stage
第九行 collect操作将计算结果返回驱动程序并打印结果。会触发acion操作生成job同时会发生数据混排生成stage。

进入spark监控的UI界面能看过这个过程中生成的job、stage和task信息。如下图


collect操作生成了一个job


collect操作发生数据混排生成一个stage,reduceByKey发生数据混排生成一个stage。

在本次实验中,HFDS中的文件大小为40k,未达到HFDS的默认块大小128m,所以在HDFS中只有一个分区。

使用下面的命令查看分块信息

hadoop fsck /"fileName" -files -blocks -locations -racks

所以在spark程序执行的时候每个stage会生成一个tast,共生成两个task。

下面看一下文件大小文400m被分为4块的情况,同时也能看出128m每块,最后一块是小于128m的。

同样1个job

2个stage,则task个数为2*4=8

最后做一个总结:
job数量和程序中acion的操作个数有关,每个job又会根据是否需要数据混排生成一个或多个stage。
stage的数量取决于程序中需要进行数据混排的操作的数量(文章末尾会讲解数据混排操作),stage会根据RDD分区的数量生成相对应数量的task。
task的内容和stage完全相同,当分区数量为n时,会有n个相同效果的task被分发到执行程序中执行。数量取决于job、stage和文件分块数的乘积。
taskNum=jobNumstageNumblockNum

数据混排

数据混排涉及到父RDD和子RDD的依赖关系。在窄依赖性中,父RDD的每个分区最多可以由子RDD的一个分区使用,换句话说,就是窄依赖关系中一个子RDD分区只能从一个父RDD分区中生成,这样就不会设计到数据的移动。例如,使用map函数将所有字符变为大写,只需要在当前分区上操作生成新的分区即可,不需要其他分区的数据。在宽依赖性中,多个子分区都可以依赖于某个父分区或者一个子分区依赖多个父分区。例如,reduceBykey函数根据键值统计单词出现的次数需要所有的分区参与生成一个排序后的RDD。依赖性如图所示。

你可能感兴趣的:(spark中job、stage和task之间的关系)