Spark其他调优的点

并行度

为了充分利用集群,可以调整每一个操作的并行度。Spark已经给各个参数默认设置了并行任务的数量。可以做的就是传入操作的第二参数来改变并行度,或者通过spark.default.parallelism参数来设置默认并行度。一般,官方推荐每一个CPU核对应2~3个Task。

mapPartitions 代替 map

map算子每一个元素执行一次func,而mapPartitions 算子每一个分区执行一次func,可见mapPartitions 的效率较高。

当分区数据量特别大的时候,mapPartitions 一次持有太多数据对象,gc无法回收,导致OOM。所以mapPartitions 不适用与粪污数据量特别大的场景。类似的情况也会在foreachPartition算子中出现。

Reduce Task的内存使用

一般出现OOM,通常是因为一次性处理的数据集太大,比如groupByKey,sortByKey, groupByKey, reduceByKey, join等算子中的shuffle操作,内部每一个task操作的数据量都很大。要解决这个问题,最简单的办法就是提高并行度,这样整个数据集被切分得更小,Spark支持重用Executor JVM,使多个task在同一JVM中执行,相应减少Task启动时间,所以可以安全的增大并行度。

使用广播变量

可以有效减小Task的序列化大小、启动代价。如果Task使用一个大对象或查找表,考虑使用广播变量。那么什么对象算大对象呢?大于20K就算大对象。

reduceByKey 代替 groupByKey

reduceByKey 在shuffle前会预聚合,类似MapReduce在map端Combine。数据量小了,内存、磁盘IO用量也少了,也减少网络消耗。groupByKey是直接shuffle。

善用coalesce 和 repartition

经过某些计算以后,数据量大为减少,也有可能有些分区数据要比其他分区多得多,可以善用coalesce 与repartition减少分区,节约资源。如:
合并分区,合并前后分区数相差不大,直接使用coalesce,无shuffle
合并分区,合并前后分区数相差大,推荐coalesce及第二参数为true,有shuffle
拆分区,使用repartition或者coalesce及第二参数为true,有shuffle

另外SparkSQL中,不允许用户自定义并行度,可以对转换后的RDD调用repartition来调整。

数据本地化

数据本地化对Spark 作业的性能有重要影响。最好的情况是数据跟执行代码都在一个进程里。如果不是,尽量移动执行代码到有数据的机器上,而不是移动数据到执行代码的机器上。也有更极端的情况,比如一台空闲的机器上也没有数据,这时Spark会等一下,一旦超时就开始把数据移动给这个空闲的机器。至于这个超时的时间可在spark.locality 参数中配置,其他具体配置可见配置

调整map、reduce端buffer大小
  • map端缓冲大小固定,如果数据量大,而buffer设置得小,会频繁spill溢写磁盘,性能低下。所以适当调大buffer大小(配置参数spark.shuffle.file.buffer,默认32K),减少溢写概率或次数提高性能。
  • reduce端buffer大小决定了Task每次缓冲的数据量,如果buffer设置得小,会出现很多次拉取数据操作。适当增加buffer大小(配置参数spark.reducer.maxSizeInFlight,默认48M),可以减少拉取数据的次数,也就减少网络传输次数,进而提升性能。
调整reduce端失败重试拉取次数和间隔

运行出错是常见现象,比如网络不稳定,为了提高稳定性,避免导致作业执行失败,可调整失败重试次数(配置参数spark.shuffle.io.maxRetries,默认3)和等待间隔(配置参数spark.shuffle.io.retryWait,默认5s)

调整连接确认等待时长

运行中,Executor从其他节点上获取数据,如果碰到对方在执行GC,就会出现不响应、无法建立网络连接、网络连接超时等问题,最终,使拉取数据失败,出现尝试,增加运行时间。如果反复尝试仍不能获取,将导致整个作业失败。这时可调整连接确认等待时长(配置参数spark.network.timeout,默认120s。这个参数也可以由一下参数代替:
spark.core.connection.ack.wait.timeout,
spark.storage.blockManagerSlaveTimeoutMs,
spark.shuffle.io.connectionTimeout,
spark.rpc.askTimeout 。如果他们都设置,则使用spark.rpc.lookupTimeout,默认120s)

调整shuffle排序操作阈值

如果reduce端task的数量小于某一阈值,则map端不会进行排序,而是直接按照未经优化的方式去写数据。如果的确不需要排序操作,那么建议将这个参数(配置参数spark.shuffle.sort.bypassMergeThreshold,默认200)调大一些,大于reduce端task数量,那么此时map端就不会进行排序了,减少了排序的性能开销。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值