1、job任务的产生
声明多个转换算子变量只是创建了RDD数据结构,只有当拿到一个行动算子后,Job任务才会产生,首先spark先创建上下文对象,作为appmaster向yarn集群的resourcemanager申请资源,申请的资源进入yarn队列中排队,当排到时,yarn分配nodemanager给spark的driver和excutor
2、stage任务的划分
根据任务的宽窄依赖进行任务划分,当牵扯到宽依赖也就是重分区时,spark会切开stage,例如连续几次map和flatmap操作都是在同一个stage中,而当遇到groupbykey和reducebykey等,划分stage,而这些操作都是在driver端完成的,它会事先规划好任务后续的分区逻辑,生成执行计划
3、task的划分与产生
首先读文件时,driver事先是知道文件取自哪几台机器的,也事先知道哪几台机器上面运行有excutor,其会优先将文件指定就近的excutor读取处理;
为什么叫指定,而不是发往,因为它只负责统筹信息,并不是真的传递数据,包括读取后的map等操作,只要不牵扯到shuffle,又是同一个切片文件,就都属于同一个task,每个task内部没有数据,而是一个个的装饰者嵌套逻辑计划,driver会统计这些task放入池中,由指定的excutor进行读取和后续处理
4、excutor的执行
excutor只负责干活,处理driver发来的task任务,task内如何处理,都是由driver提前指定好的,包括该task后续是否要经过重分区重组数据,分区依据是哪个key都是由driver提前定义好
5、driver的调度管理
如果excutor出故障或数据计算出错,driver会统计到这些信息,负责任务的重跑,因为它其中记录 了依赖关系,也记录了文件的路径
6、stage的分区和并行度
spark中可以为RDD设置读取时的最小分区数,一般情况下分区个数,即为并行度,因为每个分区是独立的,因此可以独立运行同样逻辑的task增加执行效率,这里的并行度为抽象概念,其实是并发数,例如只有一个excutor且只有单核情况下,就算分区数设置为10,但其实并行度仍为1,10个task需要排队进入excutor中执行,最小分区数默认为2;
为什么说一般情况下分区个数即为并行度,试想一个情况,如果分区个数设置为2,但是有三个文件要读取,因为底层走的是Hadoop读取策略,因此在三个文件都为切片大小时,会分别对三个文件进行字节偏移量分区,而偏移量分区最后可能有余数,如果余数大于每个分区字节数的10%则会生成一个新分区,所以可能每个文件又切分为3个分区,因此最后有9个task,9个并行度
7、spark输出文件数
输出文件数为最后一个RDD的并行度,也就是task个数,首先假如我们通过对hadoop文件进行切片处理,生成了9个task,如果我们不进行重分区,也就是我们直接输出文件,则会生成9个文件;
但如果我们要进行重分区,我们想进行groupby,默认会走所有excutor并行度之和,最大效率运用excutor的并行度,倘若有2个excutor,每个excutor核数为2,则生成4个task发往excutor,最后输出文件也为4;
倘若我设置了最后的groupby算子并行度为20,则会生成20个task发往excutor,尽管无法并行同时生成20个文件,但最后文件个数也会是20个