Shuffle模块详解
来源:互联网 发布:淘宝差评被卖家骚扰 编辑:程序博客网 时间:2024/06/03 12:54
Shuffle过程即把数据打乱后重新汇聚到不同节点的过程
7.1 Hash Based Shuffle Write
每个ShuffleMapTask根据key的哈希值计算出每个key需要写入的Partition,然后把数据单独写入一个文件,下游的ShuffleMapTask或者ResultTask便会读取此文件进行计算
7.1.1 Basic Shuffle Write实现原理
val manager=SparkEnv.get.shuffleManager //创建ShuffleManager(Hash和Sort BasedShuffle)
创建Hash Based ShuffleManager
writer=manager.getWrite[Any,Any](dep.shuffleHandle,partitionId,context)(HashShuffleWrite和SortShuffleWriter)
得到Hash Based ShuffleWriter
writer.write(rdd.iterator(partition,context).asInstanceOf[Iterator[_<:Product2[Any,Any]]])执行rdd,并将结果写入文件系统
Rdd.iterator进行rdd计算,ShuffleDependency定义Aggregator是够做Map端的聚合,FileShuffleBlockManager.forMapTask()写入结果
写入完成后会将元数据信息写入MapStatus,会被保存在MapOutputTrackerMaster中
writers.numPartitions返回下游Partition数量(Task数量),每个Partition对应一个文件,文件名称shuffle_+shuffleId+_mapId+_reduceId
return writer.stop(success=true).get关闭writer并将计算结果返回
7.1.3 Shuffle Consolidate Writer
spark.shuffle.consolidateFiles设置为true,目的减少shuffle过程中产生的文件,对于运行在同一个Core的Shuffle Map Task而言,第一个Shuffle Map Task会创建一个文件,之后的会将数据直接追加到文件上,具体的实现细节在FileShuffleBlockManager.forMapTask.writers实现
FileShuffleBlockManager.ShuffleFileGroup为文件组,文件组中的每个文件对应一个partition或者下游的Task
blockManager.getDiskWriter为每个文件创建DiskBlockObjectWriter,可直接向一个文件写入数据
7.2 Sort Based Write(将所有数据写入一个文件,同时生成Index文件,Reducer利用此Index文件获取需要处理的数据)
SortShuffleManager
ShuffleMapTask会按照key对应的PartitionID进行Sort,其中同一个Partition的key不会sort
SortShuffleWriter的核心功能实现:
1)对于每个Partition创建一个scala.Array存储它所包含的key/value对,如果Array的大小超过阈值则写入外部存储,此文件的开头会记录该Partition的ID以及该文件保存了多少个数据条目
2)将所有写入外部存储的文件进行归并排序
3)生成最后的数据文件时同时生成Index索引文件
7.3 Shuffle Read
每个Stage的上边界要么需要从外部存储读取数据,要么需要读取上一个Stage的输出;下边界则要么写入文件系统(ShuffleMap Task),要么输出结果(Result Task)
7.3.1 整体流程
ShuffledRDD.compute()->ShuffleManager.getReader()->ShuffleReader.read()(ShuffleReader均是HashShuffleReader实现)->BlockStoreShuffleFetcher.fetch()会获得数据->MapOutputTracker.getServerStatuses获得数据的元数据信息->MapOutputTrackerMasterActor发送请求(MapOutputTracker.askTracker())->元数据信息保存在Seq[BlockManagerId,Seq[(BlockId,Long)]]->ShuffleBlockFetcherIterator根据数据本地性原则进行数据获取->若数据在本地则BlockManager.getBlockData()对于Shuffle数据则调用ShuffleManager.ShuffleBlockManager.getBlockData();否则如果数据在其他Executor上时,若用户使用spark.shuffle.blockTransferService是netty,则通过NettyBlockTransferService.fetchBlocks获取,如果使用nio,则通过NioBlockTransferService.fetchBlocks获取
7.3.2 数据读取策略的划分
ShuffleBlockFetchIterator.splitLocalRemoteBlocks确定划分数据的读取策略,如果数据在本地,则可以直接从BlockManager读取,若在其他Executor上,则需要网络读取
1)每次最多启动5个线程到最多5个节点上读取数据
2)每次请求的数据大小不超过spark.reducer.maxMbInFlight的五分之一
7.5.3 本地读取
在ShuffleBlockFetcherIterator.splitLocalRemoteBlocks中调用fetchLocalBlocks负责本地Block的获取,将本地Block列表存入localBlocks(BlockManager.getBlockData),其中会判断数据是否为shuffle数据,若为shuffle数据则ShuffleManager.getBlockData,对于Hash Based Shuffle而言,其ShuffleBlockManager即为FileShuffleBlockManager有两种情况,一种是consolidateFile(根据Map ID和Reduce ID获得FileGroup的一个文件,然后根据文件的offset和size读取数据);否则知己而通过ShuffleBlockID读取整个文件即可;而对于SortBased Shuffle,通过索引文件获取数据块在数据文件中的具体位置信息即IndexShuffleBlockManager.getBlockData
7.5.4 远程读取
分别为NettyBlockTransferService.fetchBlocks()和NioBlockTransferService.fetchBlocks()
ShuffleBlockFetcherIterator.sendRequest()向远程节点发起读Block请求,然后NettyBlockTransferService.fetchBlocks()->OneForOneBlockFetcher->TransportClient->NettyBlockRpcServer最终传导远程节点的BlockManager.getBlockData
7.6性能调优
7.6.1 spark.shuffle.manager默认是sort based shuffle
7.6.2 spark.shuffle.spill默认是true即指定shuffle过程中如果内存中的数据超过阈值spark.shuffle.memoryFraction设置将部分数据临时写入外部存储
7.6.3 spark.shuffle.memoryFraction(设置内存写外存的阈值)和spark.shuffle.safetyFraction(降低实际Shuffle需要的内存值)
7.6.4spark.shuffle.sort.bypassMergeThreshold用于设置Reducer的partition数目少于多少事,sort based shuffle内部不在使用归并排序,而是直接写入单独文件
在GC严重或者内存紧张时适当降低此值
7.6.5 spark.shuffle.blockTransferService默认是netty
7.6.6 spark.shuffle.consolidateFiles默认是false
7.6.7 spark.shuffle.compress默认都是true,设置Shuffle过程中是否对Shuffle数据进行压缩,如果网络是瓶颈,则设置为true,如果是CPU计算密集型应用则设置false
Spark.shuffle.spill.compress中间结果在spill到本地磁盘进行压缩,将中间结果取回进行merge时进行压缩,Disk IO成为瓶颈时,true更合理,如果是SSD,则设置为false
7.6.8spark.reducer.maxMbInFlight限制Reducer Task向其他Executor请求Shuffle数据的最大内存数,默认是48MB,需要总和考虑网卡带宽和内存- Shuffle模块详解
- spark源码系列文章------shuffle模块详解
- Python random 模块详解 sample、randint、shuffle、choice 随机函数
- Shuffle详解
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- 详解MapReduce shuffle 过程
- 详解shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- MapReduce:详解Shuffle过程
- 字符串拼接引发的BUG
- recyclerview实现瀑布流布局
- 同一台服务器(电脑)运行多个Tomcat
- 廖雪峰切片课后题
- JS运行过程,作用域和上下文的作用,自执行函数
- Shuffle模块详解
- SPRING MVC_2
- Android--ExpandableListview购物车简单功能实现
- python爬虫之反爬虫情况下的煎蛋网图片爬取初步探索
- 数据流控制文件(自己理解的,求大神指点)
- Angular2组件与Echarts饼状图交互之饼图制作
- Linux网络编程基础API--socket文件描述符API
- 2017.12.5对内网,外网的理解
- python basemap 底图