转载请标明出处:http://blog.csdn.net/bigbigdata/article/details/47293263
本文基于Spark 1.3.1
先上一些stage相关的知识点:
- DAGScheduler将Job分解成具有前后依赖关系的多个stage
- DAGScheduler是根据ShuffleDependency划分stage的
- stage分为ShuffleMapStage和ResultStage;一个Job中包含一个ResultStage及多个ShuffleMapStage
- 一个stage包含多个tasks,task的个数即该stage的finalRDD的partition数
- 一个stage中的task完全相同,ShuffleMapStage包含的都是ShuffleMapTask;ResultStage包含的都是ResultTask
下图为整个划分stage的函数调用关系图
在DAGScheduler内部通过post一个JobSubmitted事件来触发Job的提交
DAGScheduler.eventProcessLoop.post( JobSubmitted(...) )
DAGScheduler.handleJobSubmitted
既然这两个方法都是DAGScheduler内部的实现,为什么不直接调用函数而要这样“多此一举”呢?我猜想这是为了保证整个系统事件模型的完整性。
DAGScheduler.handleJobSubmitted部分源码及如下
private[scheduler] def handleJobSubmitted(jobId: Int,
finalRDD: RDD[_],
func: (TaskContext, Iterator[_]) => _,
partitions: Array[Int],
allowLocal: Boolean,
callSite: CallSite,
listener: JobListener,
properties: Properties) {
var finalStage: ResultStage = null
try {
//< 创建finalStage可能会抛出一个异常, 比如, jobs是基于一个HadoopRDD的但这个HadoopRDD已被删除
finalStage = newResultStage(finalRDD, partitions.size, jobId, callSite)
} catch {
case e: Exception =>
return
}
//< 此处省略n行代码
}
该函数通过调用newResultStage函数来创建唯一的ResultStage,也就是finalStage。调用newResultStage时,传入了finalRDD、partitions.size等参数。
跟进到DAGScheduler.newResultStage
private def newResultStage(
rdd: RDD[_],
numTasks: Int,
jobId: Int,
callSite: CallSite): ResultStage = {
val (parentStages: List[Stage], id: Int) = getParentSt

本文详细剖析Spark 1.3.1版本的DAGScheduler如何将Job划分为ShuffleMapStage和ResultStage。DAGScheduler根据ShuffleDependency划分Stage,每个Stage包含相同任务,Stage ID反映了其在DAG中的位置。文中逐步解析Stage创建过程,解释了Stage之间的依赖关系和ID的生成逻辑。

858

被折叠的 条评论
为什么被折叠?



