1、普通的shuffle过程
①假设节点上有4个ShuffleMapTask,节点上有2个cup core
②ShuffleMapTask的输出,称为shuffle过程的第一个rdd,即MapPartitionRDD
③每个ShuffleMapTask会为每一个task创建一份bucket内存缓存,以及对应的ShuffleBlockFile磁盘文件
④ShuffleMapTask输出结束后,封装输出数据信息和输出状态等MapStatus发送给DAGSchduler的MapOutputTrackerMaster中
⑤ResultTask通过BlockStoreShuffleFetcher从MapOutputTrackerMaster从MapOutputTrackerMaster的MapStatus中获取文件位置、文件大小等信息
⑥ResultTask获取到信息后,通过BlockManager拉取ShuffleBlockFile文件
⑦ResultTask获取到数据,形成一个rdd,即ShuffledRDD,数据优先放入内存,其次放入磁盘
⑧对每个ResultTask的数据聚合后,最终生成MapPartitionRDD
2、shuffle操作的两个特点
①在spark早期版本中,bucket缓存是非常重要的,因为ShuffleMapTask将所有的数据写入到内存后,才刷新数据到磁盘。存在的问题,如果map side的数据过多,容易造成内存溢出。在spark的新版本中,优化了内存是100KB,数据写入达到磁盘的阈值后,就会将数据一点一滴的刷新到磁盘。
新版本的优化,其优点是不容易发生内存溢出;缺点在于如果内存过小,可能发生过多的磁盘IO操作;所以,这个内存的大小在实际生产业务中会根据情况调优的。
②与Hadoop MapReduce相比,MapReduce是将所有的数据都写入到本地磁盘文件后,才启动reduce操作,因为mapreduce默认实现了要根据key对数据排序。Spark没有实现这一机制,在ShuffleMapTask端开始输出数据,ReduceTask就可以开始拉去数据,执行聚合函数和自定义算子。
spark这种机制的相对于mapreduce的数据输出,速度会快很多,但是mapreduce在reduce阶段可以对key对应的数据进行操作,spark提供不了这种机制,只有通过聚合函数,如groupByKey等,先shuffle,有MapPartitionRDD之后,调用算子对key对应的数据,进行操作。
3、优化后的shuffle操作原理
对于普通的shuffle操作,存在一个问题,100个ShuffleMapTask和100个ResultTask会存在100*100=1万个