Spark源码系列之Spark内核——Shuffle
来源:互联网 发布:js遍历特定标签 编辑:程序博客网 时间:2024/06/05 16:41
假设有Map Tasks=M,Reduce Tasks=R,则Spark会根据Map Tasks和Reduce Tasks数量生成ShuffleFile=M*R:
Spark1.2以后就有实现了两种Shuffle:Hash Shuffle和Sort Shuffle。
1.Hash Shuffle
1.1Basic Hash Shuffle
Hash Shuffle是不用对数据进行排序的。因此Shuffle Write的职责很简单:将数据 partition 好,并持久化。之所以要持久化,一方面是要减少内存存储空间压力,另一方面也是为了 fault-tolerance。Shuffle Write的任务很简单,那么实现也很简单:将 Shuffle Write的处理逻辑加入到ShuffleMapStage(ShuffleMapTask所在的Stage)的最后,该Stage的 final RDD每输出一个record就将其partition并持久化。
ShuffleMapTask的执行过程:先利用pipeline计算得到final RDD中对应的partition的records。没得到一个record就将其送到对应的bucket里,具体哪个bucket由partitioner.getPartition(record._1)决定。每个bucket里面的数据会不断被写到本地磁盘上,形成一个ShuffleBlockFile,或者简称FileSegment。之后的Reducer会去fetch属于自己的FileSegment,从而进入Shuffle Read阶段。
这是最基本的Hash Shuffle。每个Map Task都要将输出写到多个文件中。
假设有Map Tasks=M,Reduce Tasks=R,则Spark会根据Map Tasks和Reduce Tasks数量生成ShuffleFile=M*R。
这种实现就导致两个问题:
- 产生的FileSegment过多。一般Spark Job的M和R都很大,因此磁盘上会存在大量的数据文件。
- 缓冲区占用内存空间大。假设每个buffer有100Kb,且有1000个Reducers和10个Mappers/Executor。那么buffer占用的内存总量是:100Kb*10000*10=10GB/Executor。10GB/Executor对于buffer,是不能接受的。最简单直接的解决方法是减小buffer的大小,但也不能太小。
1.2Consolidate Hash Shuffle
对于第一个问题,Spark给出了一种加强版的Hash Shuffle。每个Executor的每个Bucket映射到一个文件分段。可以明显看出,在一个core上连续执行的ShuffleMapTask可以共用一个输出文件ShuffleFile。先执行完的ShuffleMapTask形成ShuffleBlock i(即bucket),后执行的ShuffleMapTask可以将输出数据直接追加到ShuffleBlock i后面,形成ShuffleBlock i',每个ShuffleBlock被称为FileSegment。下一个 stage 的 reducer 只需要 fetch 整个 ShuffleFile 就行了。这样,每个 worker 持有的文件数降为 cores * R。FileConsolidation 功能可以通过spark.shuffle.consolidateFiles=true来开启。
2.Sort Shuffle
在Hadoop中,Shuffle阶段是要对数据进行排序的,即Reducer接收到的数据都是已经排好序的。在Spark1.2之后,也提供了Sort Shuffle。
在Sort Shuffle中,每个MapTask会生成一个ShuffleFile和一个IndexFile。
val partitionLengths = sorter.writePartitionedFile(blockId, context, outputFile)shuffleBlockResolver.writeIndexFile(dep.shuffleId, mapId, partitionLengths)
3.Shuffle的选择
在SparkEnv中,我们可以看到:// Let the user specify short names for shuffle managersval shortShuffleMgrNames = Map( "hash" -> "org.apache.spark.shuffle.hash.HashShuffleManager", "sort" -> "org.apache.spark.shuffle.sort.SortShuffleManager", "tungsten-sort" -> "org.apache.spark.shuffle.unsafe.UnsafeShuffleManager")val shuffleMgrName = conf.get("spark.shuffle.manager", "sort")val shuffleMgrClass = shortShuffleMgrNames.getOrElse(shuffleMgrName.toLowerCase, shuffleMgrName)val shuffleManager = instantiateClass[ShuffleManager](shuffleMgrClass)
Spark是允许我们自己实现Shuffle的。从代码中可以发现,Hash Shuffle对应的是org.apache.spark.shuffle.hash.HashShuffleManager类,Sort Shuffle对应的是org.apache.spark.shuffle.sort.SortShuffleManager类。而Spark默认采用的是Sort Shuffle,“sort”大小写没关系。如果用户配置的spark.shuffle.manager在shortShuffleMgrNames中没有查到,则选用用户自定义的Shuffle。用户自定义的Shuffle必须继承ShuffleManager类,重写里面的一些方法。
- Spark源码系列之Spark内核——Shuffle
- Spark源码系列之Spark内核——Job提交
- Spark源码系列之Spark内核——Task运行
- Spark源码系列之Spark内核——Storage模块
- spark源码剖析之----Shuffle
- Spark源码解析——Shuffle
- Spark源码走读6——Shuffle
- spark源码系列文章------shuffle模块详解
- spark-shuffle-源码分析
- 【spark】spark之shuffle调优
- Spark Shuffle之Hash Shuffle
- Spark Shuffle之Sort Shuffle
- Spark源码学习(6)——Shuffle
- Spark源码解读(6)——Shuffle过程
- Spark Shuffle之SortShuffleWriter
- Spark 之 shuffle优化
- Spark源码系列(六)Shuffle的过程解析 - 岑玉海
- Spark源码系列(六)Shuffle的过程解析
- linux sed简单使用
- Linux使用Shell脚本实现ftp的自动上传下载
- Windows环境下使用Sublime text2进行lua的配置
- 如何代码设置以管理员身份启动程序
- Java clone() 浅克隆与深度克隆
- Spark源码系列之Spark内核——Shuffle
- UIColor RGB颜色对照表
- BIEE11.1.1.9.0 “因”字出现乱码
- html5的本地存储问题
- JAVA 学习笔记(二)
- GET与POST方法长度限制
- java 学习笔记(一)
- mac版本的cornerstone的破解方法,永久使用
- java错误和异常