Spark shuffle过程解析,在Spark执行过程中,StageScheduler 负责阶段stage的划分,然后把每一个stage打包成TaskSetManager传给TaskScheduler,但是一个阶段执行完毕后,再传下一个stage,这里需要涉及到上游stage 写数据,下游数据读数据,
这里就是shuffle过程,有上游的ShuffleMapStage写数据
历史shuffle演变过程
1.每个task写一份文件,下游的task从这份文件中查找数据,这样查找时间长
2.每个task根据下游task任务数量,分别生成task任务数量文件,下游task每个取一份文件,小文件数量多
3.在一个Excetor中,生成下游task任务数量文件,excetor中所有任务都把数据按分区写入这几个文件中
4.在一个Excetor中,生成一个index文件和一个data文件,excetor所有任务都把数据按索引文件和data文件写入
5.在4的基础上增加了每个上游task的存储的临时文件,再合并成index和data文件
在ShuffleMapStage的writer对象中,其中有处理器
获取写对象
override def getWriter[K, V](
handle: ShuffleHandle,
mapId: Long,
context: TaskContext,
metrics: ShuffleWriteMetricsReporter): ShuffleWriter[K, V] = {
val mapTaskIds = taskIdMapsForShuffle.computeIfAbsent(
handle.shuffleId, _ => new OpenHashSet[Long](16))
mapTaskIds.synchronized { mapTaskIds.add(context.taskAttemptId()) }
val env = SparkEnv.get
handle match {
case unsafeShuffleHandle: SerializedShuffleHandle[K @unchecked, V @unchecked] =>
new UnsafeShuffleWriter(
env.blockManager,
context.taskMemoryManager(),
unsafeShuffleHandle,
mapId,
context,
env.conf,
metrics,
shuffleExecutorComponents)
case bypassMergeSortHandle: BypassMergeSortShuffleHandle[K @unchecked, V @unchecked] =>
new BypassMergeSortShuffleWriter(
env.blockManager,
bypassMergeSortHandle,
mapId,
env.conf,
metrics,
shuffleExecutorComponents)
case other: BaseShuffleHandle[K @unchecked, V @unchecked, _] =>
new SortShuffleWriter(
shuffleBlockResolver, other, mapId, context, shuffleExecutorComponents)
}
}
根据处理器返回不同的写对象,具体写对象满足条件如下