Spark Shuffle笔记整理

一、Spark Shuffle介绍?

1、Shuffle—>“洗牌”,

在Spark中Shuffle的目的是为了保证每一个key所对应的value都会汇聚到同一个节点上去处理和聚合。

2、Spark中,什么情况下会发生shuffle?

reduceByKey、groupByKey、sortByKey、countByKey、join等操作。

3、Spark中的Shuffle包括两种:

HashShuffle
SortShuffle

二、HashShuffle运行原理

SortShuffle的运行机制分成两种:

普通运行机制:

Shuffle Write阶段:

由于Stage后面紧跟了另一个Stage,所以数据落地会发生在Shuffle Write阶段。为了将分区中数据相同的key写入一个分区文件中,需要将task计算结果的key的hashcode值与Reduce task个数取模,从而确定将结果写入哪个分区文件中,这样即可保证相同的key在一个分区文件中。为了加快向磁盘写文件的速度,需要事先设置一个buffer作为缓存,每个buffer的大小是32K。

Shuffle Red阶段:

Reduce task从上个Stage的task节点中拉取属于自己的分区文件,这样即可保证每一个Key所对应的Value都会在同一个节点上。拉取的过程属于现拉现用。
在这里插入图片描述

合并机制:

倘若Executor只有一个core,所以每次只能有一个task执行,当第一个task执行完成后,第二个task会复用第一个task所创建的buffer和磁盘文件,从而减少磁盘文件的个数。
在这里插入图片描述

三、SortShuffle运行原理

SortShuffle的运行机制也分成两种:

普通运行机制:

在这里插入图片描述
由于Spark只是一个计算框架,没有办法严格控制Executor内存,只能采取监控的方式去监控内存的情况,内存数据初始值的大小大约默认为5M,当超出5M的时候,例如5.02M,监控内存数据的对象就会再去申请5.02*2-5=5.04M内存,如果申请到内存就不必进行溢写,否则再进行溢写。

Shuffle Write阶段:

溢写到磁盘的过程与MapReduce的ShuffleWrite阶段一样。
区别:
内存数据初始值是5M大小,它可以申请扩大,而MapReduce中的Buffer是固定的100M。
溢写除了生成磁盘文件,还有索引文件,索引文件是对磁盘文件的描述,还有记录每个分区的起始位置以及终止位置。

Shuffle Red阶段:

Reduce Task首先会解读索引文件,然后拉取相应分区的数据,然后再处理。

bypass运行机制

在这里插入图片描述
bypass运行机制与普通运行机制相比,缺少了忘内存数据存放、排序。除此之外,其余流程一样。
bypass运行机制的触发条件:
shuffle reduce task数量小于spark.shuffle.sort.bypassMergeThreshold参数的值。

四、Shuffle过程中,磁盘小文件寻址问题

1、Map task执行完毕后,将自己的执行结果信息(比如:磁盘小文件的位置、最终执行状态信息)封装到mapstatus中,然后调用本进程中的MapOutputTrackerWorker,将mapstatus对象发送给Driver中的MapOutputTrackerWorker。
2、Reduce task会调用自己进程中的MapOutputTrackerWorker对象去向MapOutputTrackerWorker获取磁盘小文件的位置信息,然后将位置信息给BlockManagerSlave去拉取磁盘小文件。(默认会启动5个子线程去拉取数据,但5个子线程总共拉取的数据量不能超过64M)。拉来的数据会存在shuffle聚合内存中(20%x80%),以供Reduce task计算。
注:
Reduce task中的计算模式也是pipeline管道计算模式。

五、Shuffle可能面临的问题

由HashShuffle的流程图可知:磁盘小文件(分区文件)的个数=m(map task num)*r(reduce task num)
当磁盘小文件过多时,带来的问题有:

write阶段会创建大量写文件的对象
read阶段拉取数据需要进行多次网络传输
read阶段会创建大量读文件的对象
读写对象过多造成JVM内存不足,从而导致内存溢出

六、Executor的内存管理

Excutor内存管理方式有两种:

静态的内存管理:

unroll:用来进行反序列化。
两块防止OOM的内存,可以供JVM使用

统一的内存管理:

统一内存管理中,75%中的两块内存可以互相借用,但是有最大限度。

七、Shuffle调优

1、spark.shuffle.file.buffer

默认值:32k
参数说明:该参数用于设置shuffle write task的BufferedOutputStream的buffer缓冲大小。将数据写到磁盘文件之前,会先写入buffer缓冲中,待缓冲写满之后,才会溢写到磁盘。
调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如64k),从而减少shuffle write过程中溢写磁盘文件的次数,也就可以减少磁盘IO次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

2、spark.reducer.maxSizeInFlight

默认值:48M
参数说明:该参数用于设置shuffle read task的buffer缓冲大小,而这个buffer缓冲决定了每次能够拉取多少数据。
调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如96m),从而减少拉取数据的次数,也就可以减少网络传输的次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

3、spark.shuffle.io.maxRetries

默认值:3
参数说明:shuffle read task从shuffle write task所在节点拉取属于自己的数据时,如果因为网络异常导致拉取失败,是会自动进行重试的。该参数就代表了可以重试的最大次数。如果在指定次数之内拉取还是没有成功,就可能会导致作业执行失败。
调优建议:对于那些包含了特别耗时的shuffle操作的作业,建议增加重试最大次数(比如60次),以避免由于JVM的full gc或者网络不稳定等因素导致的数据拉取失败。在实践中发现,对于针对超大数据量(数十亿~上百亿)的shuffle过程,调节该参数可以大幅度提升稳定性。
shuffle file not find taskScheduler不负责重试task,由DAGScheduler负责重试stage

4、spark.shuffle.io.retryWait

默认值:5s
参数说明:具体解释同上,该参数代表了每次重试拉取数据的等待间隔,默认是5s。
调优建议:建议加大间隔时长(比如60s),以增加shuffle操作的稳定性。

5、spark.shuffle.memoryFraction

默认值:0.2
参数说明:该参数代表了Executor内存中,分配给shuffle read task进行聚合操作的内存比例,默认是20%。
调优建议:在资源参数调优中讲解过这个参数。如果内存充足,而且很少使用持久化操作,建议调高这个比例,给shuffle read的聚合操作更多内存,以避免由于内存不足导致聚合过程中频繁读写磁盘。在实践中发现,合理调节该参数可以将性能提升10%左右。

6、spark.shuffle.manager

默认值:sort
参数说明:该参数用于设置ShuffleManager的类型。Spark 1.5以后,有三个可选项:hash、sort和tungsten-sort。HashShuffleManager是Spark 1.2以前的默认选项,但是Spark 1.2以及之后的版本默认都是SortShuffleManager了。tungsten-sort与sort类似,但是使用了tungsten计划中的堆外内存管理机制,内存使用效率更高。
调优建议:由于SortShuffleManager默认会对数据进行排序,因此如果你的业务逻辑中需要该排序机制的话,则使用默认的SortShuffleManager就可以;而如果你的业务逻辑不需要对数据进行排序,那么建议参考后面的几个参数调优,通过bypass机制或优化的HashShuffleManager来避免排序操作,同时提供较好的磁盘读写性能。这里要注意的是,tungsten-sort要慎用,因为之前发现了一些相应的bug。

7、spark.shuffle.sort.bypassMergeThreshold

默认值:200
参数说明:当ShuffleManager为SortShuffleManager时,如果shuffle read task的数量小于这个阈值(默认是200),则shuffle write过程中不会进行排序操作,而是直接按照未经优化的HashShuffleManager的方式去写数据,但是最后会将每个task产生的所有临时磁盘文件都合并成一个文件,并会创建单独的索引文件。
调优建议:当你使用SortShuffleManager时,如果的确不需要排序操作,那么建议将这个参数调大一些,大于shuffle read task的数量。那么此时就会自动启用bypass机制,map-side就不会进行排序了,减少了排序的性能开销。但是这种方式下,依然会产生大量的磁盘文件,因此shuffle write性能有待提高。

问题思考

Application在执行的过程中,出现了类似reduce OOM的错误原因以及解决办法?
三种解决方案:
1、提高Executor的内存
2、提高shuffle聚合的内存比例
3、减少每次拉取的数据量

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值