最近任务在大量shuffle时,发现了shuffleread时候特别慢,查了相关的参数做一下记录。

spark.reducer.maxSizeInFlight

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

spark.shuffle.memoryFraction

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

spark.shuffle.file.buffer

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

spark.shuffle.sort.bypassMergeThreshold

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

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。

spark.shuffle.consolidateFiles

  • 默认值:false
  • 参数说明:如果使用HashShuffleManager,该参数有效。如果设置为true,那么就会开启consolidate机制,会大幅度合并shuffle write的输出文件,对于shuffle read task数量特别多的情况下,这种方法可以极大地减少磁盘IO开销,提升性能。
  • 调优建议:如果的确不需要SortShuffleManager的排序机制,那么除了使用bypass机制,还可以尝试将spark.shffle.manager参数手动指定为hash,使用HashShuffleManager,同时开启consolidate机制。在实践中尝试过,发现其性能比开启了bypass机制的SortShuffleManager要高出10%~30%。

spark.maxRemoteBlockSizeFetchToMem(默认512m)

当远程块的大小以字节计超过此阈值时,将获取到磁盘。这是为了避免占用太多内存的巨大请求。默认情况下,这只对> 2GB的块启用,因为无论有什么资源可用,这些块都不能直接提取到内存中。但是,它可以被降低到一个更低的价值。以避免在较小的块上使用太多的内存。注意,此配置将影响洗牌获取和块管理器远程块获取。对于启用外部shuffle服务的用户,此功能只能在外部使用

( 要求:spark.shuffle.service.enabled = true )
 

======================================================================

spark的shuffle是先shuffle write,再shuffle read。

shuffle write 的并行度由父RDD的并行度决定。

java spark 并发响应慢 spark 并发参数_java spark 并发响应慢

 

参考文章:

spark shuffle参数调优 - 云+社区 - 腾讯云

这是官方各个参数含义

Spark 配置 — Spark 2.2.x 中文文档 2.2.1 文档

这是目前一个任务的配置,做参考

--conf spark.yarn.job.owners=xxx
--conf spark.yarn.executor.memoryOverhead=2048 
--conf spark.sql.shuffle.partitions=2000 
--conf spark.yarn.appMasterEnv.JAVA_HOME=/opt/soft/openjdk1.8.0 
--conf spark.executorEnv.JAVA_HOME=/opt/soft/openjdk1.8.0 
--conf spark.dynamicAllocation.enabled=true 
--conf spark.shuffle.service.enabled=true 
--conf spark.cross.dc.inputs.location.prefix.substitute.enabled=false 
--conf spark.dynamicAllocation.minExecutors=2 
--conf spark.dynamicAllocation.maxExecutors=700 
--conf spark.dynamicAllocation.executorIdleTimeout=600s 
--conf spark.hadoop.parquet.enable.summary-metadata=true 
--conf spark.speculation=true 
--conf spark.speculation.multiplier=2 
--conf spark.speculation.quantile=0.5 
--conf spark.scheduler.executorTaskBlacklistTime=300000 
--conf spark.shuffle.compress=false 
--conf spark.shuffle.spill.compress=false 
--conf spark.default.parallelism=2000
--conf spark.remote.shuffle.service.enabled=true 
--conf spark.serializer=org.apache.spark.serializer.KryoSerializer
--conf spark.reducer.maxSizeInFlight=96m
--conf spark.shuffle.io.retryWait=20s
--conf spark.shuffle.memoryFraction=0.4