在早期版本的Spark中,shuffle过程没有磁盘读写操做,是纯内存操做,后来发现效率较低,且极易引起OOME,较新版本的Shuffle操做都加入了磁盘读写进行了改进。
一、未经优化的HashShuffleManager:上一个stage中每个task会对下一个stage的每个task写一份数据文件,假定上一个stage有N个task,下一个stage有M个task,此时由上到下造成N个1对M的映射关系,总共产生【N M】个文件。这种方式的优势是思路简单,数据文件的逻辑隔离性更强。缺点是在磁盘上产生的文件个数太多,每一个文件的读写都须要创建管道等操做,过多的文件势必增长额外的开销,效率较低。【同将多个小文件打包为一个大文件再拷贝,比直接拷贝多个小文件更快,一个道理】
二、优化过的HashShuffleManager:上一个stage中每个task共同写下一个stage的每个task独有的数据文件,假定上一个stage有N个task,下一个stage有M个task,此时由上到下造成M个N对1的映射关系,总共产生M个文件(文件数量只取决于下一个stage的task数量)。因为文件数量的减小,性能获得了必定的提高。
**
三、SortShuffleManager:这是当前版本中使用的方式,进一步减小数据文件个数,阶段之间只经过2个文件来传递数据【索引文件、数据文件】。在上一个阶段中,每一个task都将数据在内存中进行排序生成文件(若是内存不够用就溢写到磁盘),将多个排序后的文件合并到同一个数据文件中,配合索引文件,下游task就能高效的完成读取操做。
因为排序操做是一个相对低效的操做,因此在小数据量时可使用Hash算法来达到快速定位的目的。此时就轮到bypass机制,其内容是当shuffle-map-task数量小于bypassMergeThreshold(默认200个)时或者不是聚合类shuffle,就不采用排序而换为Hash操做。算法