Spark 调优

本文详细介绍了Spark性能调优的四个主要方面:常规性能调优、算子调优、Shuffle调优和JVM调优。包括资源分配、RDD优化、并行度调节、广播变量、Kryo序列化、mapPartitions与foreachPartition的使用、reduceByKey预聚合等策略,以及如何调节map和reduce端缓冲区大小、重试和等待间隔,还有JVM内存管理和Executor堆外内存调节等,旨在提升Spark作业的效率和运行速度。
摘要由CSDN通过智能技术生成

一、常规性能调优

1.1 最优资源配置

Spark 性能调优的第一步,就是为任务分配更多的资源,在一定范围内,增加资源的分配与性能的提升是成正比的,实现了最优的资源配置,在此基础上再考虑进行后面论述的性能调优策略。

资源的分配在使用脚本提交 Spark 任务时进行指定,标准的 Spark 任务提交脚本如下所示:

bin/spark-submit \
--class com.atguigu.spark.Analysis \
--master yarn
--deploy-mode cluster
--num-executors 80 \
--driver-memory 6g \
--executor-memory 6g \
--executor-cores 3 \
/usr/opt/modules/spark/jar/spark.jar \

可以进行分配的资源如表所示:
在这里插入图片描述

调节原则:尽量将任务分配的资源调节到可以使用的资源的最大限度。

对于具体资源的分配,分别讨论 Spark 的两种 Cluster 运行模式:
1、第一种是 Spark Standalone 模式,在编写 submit 脚本的时候,就根据可用的资源情况进行资源的分配,比如说集群有 15 台机器,每台机器为 8G 内存,2 个 CPU core,那么就指定 15 个 Executor,每个 Executor 分配 8G内存,2个CPU core。

2、第二种是 Spark Yarn 模式,由于 Yarn 使用资源队列进行资源的分配和调度,在编写 submit 脚本的时候,就根据 Spark 作业要提交到的资源队列,进行资源的分配,比如资源队列有 400G 内存,100 个 CPU core,那么指定 50 个 Executor,每个 Executor 分配 8G 内存,2 个 CPU core。

对各项资源进行调节后,得到的性能提升会有如下表现:
在这里插入图片描述

1.2 RDD 优化

1、RDD 复用
在对RDD进行算子时,要避免相同的算子和计算逻辑之下对RDD进行重复的计算。
在这里插入图片描述
对上图中 RDD 计算架构进行修改,得到优化结果:
在这里插入图片描述

2、RDD 持久化
在 Spark 中,当多次对同一个 RDD 执行算子操作时,每一次都会对这个 RDD 以及之前的父 RDD 重新计算一次,这种情况是必须要避免的,对同一个 RDD 的重复计算是对资源的极大浪费,因此,必须对多次使用的 RDD 进行持久化,通过持久化将公共 RDD 的数据缓存到内存/磁盘中,之后对于公共 RDD 的计算都会从内存/磁盘中直接获取 RDD 数据。

对于RDD的持久化,有两点需要说明:
(1) RDD 的持久化是可以进行序列化的,当内存无法将 RDD 的数据完整的进行存放的时候,可以考虑使用序列化的方式减小数据体积,将数据完整存储在内存中。

(2) 如果对于数据的可靠性要求很高,并且内存充足,可以使用副本机制,对 RDD 数据进行持久化。当持久化启用了副本机制时,对于持久化的每个数据单元都存储一个副本,放在其他节点上面,由此实现数据的容错,一旦一个副本数据丢失,不需要重新计算,还可以使用另外一个副本。

3、RDD 尽可能早的 filter 操作
获取到初始 RDD 后,应该考虑尽早地过滤掉不需要的数据,进而减少对内存的占用,从而提升 Spark 作业的运行效率。

1.3 并行度调节

Spark 作业中的并行度指各个 stage 的 task 的数量。

如果并行度设置不合理而导致并行度过低,会导致资源的极大浪费,例如,20 个 Executor,每个 Executor 分配 3 个 CPU core,而 Spark 作业有 40 个 task,这样每个 Executor 分配到的 task 个数是 2 个,这就使得每个 Executor 有一个 CPU core 空闲,导致资源的浪费。

理想的并行度设置,应该是让并行度与资源相匹配,简单来说就是在资源允许的前提下,并行度要设置的尽可能大,达到可以充分利用集群资源。合理的设置并行度,可以提升整个 Spark 作业的性能和运行速度。

Spark 官方推荐,task 数量应该设置为 Spark 作业总 CPU core 数量的 2-3 倍。之所以没有推荐 task 数量与 CPU core 总数相等,是因为 task 的执行时间不同,有的 task 执行速度快而有的 task 执行速度慢,如果 task 数量与 CPU core 总数相等,那么执行快的 task 执行完成后,会出现 CPU core 空闲的情况。如果 task 数量设置为 CPU core 总数的 2~3 倍,那么一个 task 执行完毕后,CPU core 会立刻执行下一个 task,降低了资源的浪费,同时提升了 Spark 作业运行的效率。

Spark 作业并行度的设置如下:

val conf = new SparkConf().set("spark.default.parallelism", "500")

1.4 广播大变量

默认情况下,task 中的算子中如果使用了外部的变量,每个 task 都会获取一份变量的复本,这就造成了内存的极大消耗。一方面,如果后续对 RDD 进行持久化,可能就无法将 RDD 数据存入内存,只能写入磁盘,磁盘 IO 将会严重消耗性能。另一方面,task 在创建对象的时候,也许会发现堆内存无法存放新创建的对象,这就会导致频繁的 GC, GC 会导致工作线程停止,进而导致 Spark 暂停工作一段时间,严重影响 Spark 性能。

假设当前任务配置了 20 个 Executor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值