CC00099.spark——|Hadoop&Spark.V15|——|Spark.v15|Spark 原理 源码|Shuffle详解|

一、Shuffle Writer
### --- Shuffle Writer:ShuffleWriter(抽象类),有3个具体的实现:

~~~     SortShuffleWriter。sortShulleWriter 需要在 Map 排序
~~~     UnsafeShuffleWriter。使用 Java Unsafe 直接操作内存,
~~~     避免Java对象多余的开销和GC 延迟,效率高
~~~     BypassMergeSortShuffleWriter。
~~~     和Hash Shuffle的实现基本相同,区别在于map task输出汇总一个文件,同时还会产生一个index file
### --- Shuffle Writer

~~~     # 源码编程实现
ShuffleWriter(org.apache.spark.shuffle.sort)
BypassMergeSortShuffleWriter(org.apache.spark.shuffle.sort)
UnsafeShuffleWriter(org.apache.spark.shuffle.sort)
SortShuffleWriter(org.apache.spark.shuffle.sort)
### --- 以上 ShuffleWriter 有各自的应用场景。分别如下:

~~~     不满足以下条件使用 SortShuffleWriter
~~~     没有map端聚合,RDD的partitions分区数小于16,777,216,
~~~     且 Serializer支持 relocation【Serializer 可以对已经序列化的对象进行排序,
~~~     这种排序起到的效果和先对数据排序再序列化一致】,使用UnsafeShuffleWriter
~~~     没有map端聚合操作 且 RDD的partition分区数小于200个,使用 BypassMergerSortShuffleWriter
### --- bypass运行机制:bypass运行机制的触发条件如下:

~~~     shuffle map task数量 <= spark.shuffle.sort.bypassMergeThreshold (缺省200)
~~~     不是聚合类的shuffle算子
### --- Bypass机制 Writer 流程如下:

~~~     每个Map Task为每个下游 reduce task 创建一个临时磁盘文件,
~~~     并将数据按key进行hash然后根据hash值写入内存缓冲,缓冲写满之后再溢写到磁盘文件;
~~~     最后将所有临时磁盘文件都合并成一个磁盘文件,并创建索引文件;
~~~     Bypass方式的Shuffle Writer机制与Hash Shuffle是类似的,在shuffle过程中会创建很多磁盘文件,
~~~     最后多了一个磁盘文件合并的过程。Shuffle Read的性能会更好;
### --- Bypass方式与普通的Sort Shuffle方式的不同在于:

~~~     磁盘写机制不同
~~~     根据key求hash,减少了数据排序操作,提高了性能
### --- Shuffle Writer 流程

~~~     数据先写入一个内存数据结构中。不同的shuffle算子,可能选用不同的数据结构
~~~     如果是 reduceByKey 聚合类的算子,选用 Map 数据结构,一边通过 Map 进行聚合,一边写入内存
~~~     如果是 join 类的 shuffle 算子,那么选用 Array 数据结构,直接写入内存
~~~     检查是否达到内存阈值。每写一条数据进入内存数据结构之后,就会判断一下,
~~~     是否达到了某个临界阈值。如果达到临界阈值的话,
~~~     那么就会将内存数据结构中的数据溢写到磁盘,并清空内存数据结构
~~~     数据排序。在溢写到磁盘文件之前,会先根据key对内存数据结构中已有的数据进行排序。
~~~     排序过后,会分批将数据写入磁盘文件。默认的batch数量是10000条,
~~~     也就是说,排序好的数据,会以每批1万条数据的形式分批写入磁盘文件
~~~     数据写入缓冲区。写入磁盘文件是通过Java的 BufferedOutputStream 实现的。
~~~     BufferedOutputStream 是Java的缓冲输出流,首先会将数据缓冲在内存中,
~~~     当内存缓冲满溢之后再一次写入磁盘文件中,这样可以减少磁盘IO次数,提升性能
~~~     重复写多个临时文件。一个 Task 将所有数据写入内存数据结构的过程中,
~~~     会发生多次磁盘溢写操作,会产生多个临时文件
~~~     临时文件合并。最后将所有的临时磁盘文件进行合并,这就是merge过程。
~~~     此时会将之前所有临时磁盘文件中的数据读取出来,然后依次写入最终的磁盘文件之中
~~~     写索引文件。由于一个 Task 就只对应一个磁盘文件,
~~~     也就意味着该task为下游stage的task准备的数据都在这一个文件中,
~~~     因此还会单独写一份索引文件,其中标识了下游各个 Task 的数据在文件中的 start offset 与 end offset
二、Shuffle MapOutputTracker
### --- Spark的shuffle过程分为Writer和Reader:

~~~     Writer负责生成中间数据
~~~     Reader负责整合中间数据
~~~     而中间数据的元信息,则由MapOutputTracker负责管理。 它负责Writer和Reader的沟通。
~~~     Shuffle Writer会将中间数据保存到Block里面,然后将数据的位置发送给MapOutputTracker。
~~~     Shuffle Reader通过向 MapOutputTracker 获取中间数据的位置之后,才能读取到数据。
### --- Shuffle Reader 需要提供 shuffleId、mapId、reduceId 才能确定一个中间数据:

~~~     shuffleId,表示此次shuffle的唯一id
~~~     mapId,表示map端 rdd 的分区索引,表示由哪个父分区产生的数据
~~~     reduceId,表示reduce端的分区索引,表示属于子分区的那部分数据
三、执行流程
### --- MapOutputTracker在executor和driver端都存在:

~~~     MapOutputTrackerMaster 和 MapOutputTrackerMasterEndpoint(负责通信) 存在于driver
~~~     MapOutputTrackerWorker 存在于 executor 端
~~~     MapOutputTrackerMaster 负责管理所有 shuffleMapTask 的输出数据,
~~~     每个 shuffleMapTask 执行完后会把执行结果(MapStatus对象)注册到 MapOutputTrackerMaster
~~~     MapOutputTrackerMaster 会处理 executor 发送的 GetMapOutputStatuses 请求,
~~~     并返回serializedMapStatus 给 executor 端
~~~     MapOutputTrackerWorker 负责为 reduce 任务提供 
~~~     shuffleMapTask 的输出数据信息(MapStatus对象)
~~~     如果MapOutputTrackerWorker在本地没有找到请求的 shuffle 的 mapStatus,
~~~     则会向MapOutputTrackerMasterEndpoint 
~~~     发送 GetMapOutputStatuses 请求获取对应的 mapStatus
四、Shuffle Reader
### --- Shuffle Reader

~~~     Map Task 执行完毕后会将文件位置、计算状态等信息封装到 MapStatus 对象中,
~~~     再由本进程中的MapOutPutTrackerWorker 对象将其发送给Driver进程的
~~~     MapOutPutTrackerMaster对象
~~~     Reduce Task开始执行之前会先让本进程中的 MapOutputTrackerWorker 
~~~     向 Driver 进程中的MapOutputTrackerMaster 发动请求,获取磁盘文件位置等信息
~~~     当所有的Map Task执行完毕后,Driver进程中的 MapOutputTrackerMaster 
~~~     就掌握了所有的Shuffle文件的信息。
~~~     此时MapOutPutTrackerMaster会告诉MapOutPutTrackerWorker磁盘小文件的位置信息
~~~     完成之前的操作之后,由 BlockTransforService 去 Executor 所在的节点拉数据,
~~~     默认会启动五个子线程。每次拉取的数据量不能超过48M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yanqi_vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值