阅读本篇文章,你应该得到spark面试中的这几个问题的答案:

  • job的概念,job是以什么为准划分的
  • stage的概念,stage是以什么为准划分的
  • task的概念,task是以什么划分的
  • rdd的宽窄依赖是什么,怎么区分

1、 概念关系图

worker和task job的区别 mapreduce job和task和work的区别_spark


其实这几个概念的理解有个比较好的思路,从stage下手;

spark在任务调度这块,将stage作为核心概念,向下:stage是一系列task的集合;向上:多个stage构成一个job,而划分job的依据是遇到action类型的算子就划分一个job;

2、job

2.1 官方说明

worker和task job的区别 mapreduce job和task和work的区别_spark_02


简单提炼一下主要的意思:

  • 调度层就是一个有向的stage依赖图调度;
  • 对每一个job计算一个stage依赖DAG图并且这个图保持RDD之间的依赖,在遇到一个可以物化的输出(action算子)时就划分为一个job,保证每个job里面拥有一个最小的可执行的调度模块
  • job划分完成后,将一系列的stage作为task的集合(taskset)提交到集群上并在task任务调度下进行具体的执行;
  • 一个taskset是完全独立不依赖其他的任务,并且可以在集群数据上立即执行;

worker和task job的区别 mapreduce job和task和work的区别_任务调度_03


这些注释更加明确的显示了job的划分依据,在整个依赖图遇到action算子就会通过submitJob方法提交一个job

2.2、代码验证

提交一个action类型的job函数:

worker和task job的区别 mapreduce job和task和work的区别_依赖图_04


图中红色框圈选出来的分别为函数的输入和输出:

输入包含rdd,对rdd的每一个partition执行的function,失败的位置,成功结果的操作器以及一些配置;

返回值是对于这个job的同步等待器!

3、stage

3.1、官方说明

worker和task job的区别 mapreduce job和task和work的区别_spark_05


简单提炼一下主要思想:

  • 图中标注的就是stage的划分依据:spark stage是被RDD DAG图中的shuffle边界划分的,简单来说,如果你的程序中出现了shuffle,那么就会以shuffle为界限,前面的构成一个stage,shuffle后的DAG构成一个stage
  • 对于窄依赖的算子,比如map,filter会形成很多的task,这些task会放到一个stage中;
  • 对于具有shuffle类型的依赖,也就是宽依赖的话,整个DAG会形成多个stage,典型的是一个写map的输出,一个读map结果并shuffle;
  • 整体来看,不同stage之间是以shuffle依赖来进行连接;

3.2、代码验证

3.2.1 Stage.scala

在了解stage的具体使用之前,我们需要知道stage是什么,主要包含哪几种主要的类别?

worker和task job的区别 mapreduce job和task和work的区别_spark_06

  • shuffle map stage
  • result stage:具体的action算子发生的地方,分别在rdd的每一个partition里面执行compute方法

对应上面两种类型的stage,相应的也会有两种生成的方法:

  • createShuffleMapStage
  • createResultStage

这里不详细介绍了,想仔细了解的童鞋可以查看源码,本篇主要讲区别和面试中遇到的一些问题。

3、task

3.1、官方说明

worker和task job的区别 mapreduce job和task和work的区别_spark_07


这里官方注释的比较少,只是说明了一个主要的定义:task是在work节点上的独立单元,会在每一个机器上进行执行;

它有几个基本的属性:

  • 每个partition启动一个task;
  • 当有很多个小文件的时候,读取的时候也会启动很多的task;
  • task是由TaskScheduler进行任务的调度的;
  • 每一个TaskScheduler只会在一个spark的上下文中起作用;