【spark新手,如有不对,请一定指正】
先说job、stage、task的关系
一个job ——> 一或多个stage ——> 一或多个task
job
所谓一个 job,就是由一个 rdd 的 action 触发的动作,可以简单的理解为,当你需要执行一个 rdd 的 action 的时候,会生成一个 job。
stage
stage的划分依靠宽、窄依赖,遇到一个宽依赖shuffle,就划分为一个stage。
spark 划分 stage 的整体思路是:调度器从DAG图末端出发,逆向遍历整个依赖关系链,遇到宽依赖就断开,划分为一个 stage;遇到窄依赖就将这个 RDD 加入该 stage 中。stage中task数目由stage末端的RDD分区个数来决定。
总的来说n个shuffle就会产生(n+1)个stage。
task
在 spark 中,Task 的类型分为 2 种:ShuffleMapTask 和 ResultTask
简单来说,DAG 的最后一个阶段会为每个结果的 partition 生成一个 ResultTask,即每个 Stage里面的 Task 的数量是由该 Stage 中最后一个 RDD 的 Partition 的数量所决定的(通过算子修改了某一个rdd的分区数量,task数量也会同步修改,比如repartition)!而其余所有阶段都会生成 ShuffleMapTask;之所以称之为 ShuffleMapTask 是因为它需要将自己的计算结果通过 shuffle 到下一个 stage 中;
注意repartition和通过参数设置的并行度的不同,参考链接:Spark 性能调优之 repartition解决spark sql低并行度问题。
task的并行度与设定的executor数量以及每个executor拥有的core数量有关,一个task使用一个core,有多少个executor*core,就可以同时运行多少个task。比如executor数量设置为100,executor_core设置为2,那么就可以同时运行100*2=200个task,即并行度为200,此时即使分区数再多,也只能同时运行200个task,剩余的task需等到有executor空闲时再运行
之前讲到,stage的划分依据是宽依赖shuffle操作,因此着重研究下宽、窄依赖
宽依赖【也叫ShuffleDependency】
父RDD的一个分区会被子RDD的多个分区使用。宽依赖是会产生shuffle的,对于groupByKey,join with inputs not co-partitioned,xxbykey(通过key分发都会产生shuffle)
窄依赖
父RDD的分区最多只会被子RDD的一个分区使用,比如map,ilter,union等
宽窄依赖根本区别:父RDD中分区内的数据,是否在子类RDD中也完全处于一个分区,如果是,窄依赖,如果不是,宽依赖。
参考链接
Spark Stage 的划分
spark中job,stage,task之间的关系
spark中job stage task关系
聊聊Spark中的宽依赖和窄依赖
Spark的Shuffle的四种机制以及参数调优