一个application运行期间可以执行多个spark job(作业),有多少作业是由多少个action操作的rdd决定。几次action,就有几个job
每个job 分为多个stage,stage划分是依据shuffleDependency(宽依赖)。每次遇到一个,就要新产生一个stage。shuffle类算子会产生新的stage。从RDD角度看,ShuffledRDD,CoGroupedRDD,SubtractedRDD会产生ShuffleDependency。
因此在我们的开发过程中,能避免则尽可能避免使用reduceByKey、sortByKey,GroupByKey,cogroupbyKey,cartensian,join、distinct、repartition等会进行shuffle的算子,尽量使用map类的非shuffle算子。这样的话,没有shuffle操作或者仅有较少shuffle操作的Spark作业,可以大大减少性能开销。
每个stage有多少个task(任务)是由多少partition决定。一个partition可以由一个task来处理。partition是由pationtioner(分区器)决定。
牛人可以根据业务的数据分布情况自定义分区器,让每个partition得到的数据量大小差不多,避免数据倾斜。
抽象类Task有两个子类实现分别是ResultTask和ShuffleMapTask。ResultTask会将计算结果返回到driver application,而ShuffleMapTask是把RDD中的元素依照ShuffleDependency中的定义发送到多个bucket中。
任务提交过程中主要涉及Driver和Executor两个节点:
Driver侧在任务提交过程中最主要解决如下几个问题:
1,RDD依赖性分析,生成DAG
2,根据RDD DAG将Job分割为多个Stage
3,Stage一经确认,即生成相应的Task,将task分发到Executor