Spark调优

本文详细介绍Spark集群搭建与任务提交流程,深入探讨如何通过调整资源分配、提高并行度、优化代码逻辑、使用高效算子及数据结构等策略,实现Spark应用性能的全面提升。

1.搭建集群

在Spark安装路径下 spark/conf/spark-env.sh配置:

SPARK_WORKER_CORES=XXX

SPARK_WORKER_MEMORY=XXX

2.提交任务

提交任务命令,最好使用脚本化提交,可以在提交任务时给当前spark应用程序足够的资源,提交命令:

./spark-submit --master spark://node1:7077 -class ... jar ...

可以在-master 之后-class之前添加以下参数

--dirver-cores:指定Driver端使用的core数。

--driver-memory:指定Driver端的使用内存数,如果Driver端有回收数据广播的时候,可以多申请内存。

--executor-cores:指定executor端使用的core数量,一个core在某个时刻并行执行1个task任务,executor中的core越多并行的task任务越多。

--executor-memory:指定Executor端使用的内存,如果shuffle量多、对RDD持久化多、task创建任务多,可以多申请点资源。

--total-executor-cores:Standalone集群中,指定当前应用程序最多使用多少core.在Standalone集群中,默认提交一个Spark应用程序,这个Spark应用程序会使用集群中所有的资源。

--num-executor:在yarn集群中,默认为一个提交的spark应用程序启动2个Executor。

-处理以上在提交任务中可以设置参数,还可以在代码中设置(不建议硬编码)

也可以在spark提交任务的客户端中的配置文件中配置:spark/conf/spark-defaults.xml(不建议):

spark.driver.cores

spark.driver.memory

spark.executor.cores

spark.executor.memory

spark.cores.max

3.提高并行度

-SparkContext.textFile(xx,minum)

-SparkContext.parallelize(xx,num)

-SparkContext.makeRDD(xx,num)

-SparkContext.parallelizePairs(List<Tuple2<xx,xx>>,num)

-RDD的算子repartition(num)/coalesce(num)、reduceByKey(num)、join(num)、groupByKey(num),distinct(num)

-"spark.default.parallelism" Spark中默认的并行度

-自定义分区器也可以增加并行度

-"Spark.sql.shuffle.partitions"设置SparkSQL中解析成SparkJob的并行度。

-SparkStreaming中Driect模式可以增大读取的topic的partition个数。

4.代码优化

-避免创建重复的RDD,这种情况是避免某些代码逻辑不执行,逻辑混乱。

-对多次使用的RDD进行持久化,持久化算子:cache()=persist()=persist(StroageLevel.MEMORY_ONLY)

如果内存够用就使用MEMORY_ONLYJ级别,如果不是内存太充足,可以采用MEMOEY_ONLY_SER级别,相当于牺牲性能换取空间。如果使用MEMORY_ONLY_SER级别还是不能完全储存,可以使用MEMORY_AND_DISK或者MEMORY_AND_DISK_SER.

注意:对RDD进行持久化时,一定要使用Action算子触发,才能使RDD被持久化。

-尽量避免使用shuffle类的算子。利用广播变量+filter类的算子代替join

-尽量使用map端有预聚合的算子(map-combine)

5.map端预聚合的好处:

(1)减少map端shuffle的落地数据量

(2)减少reduce端拉取的数据量

(3)极少节点之间传输的数据量

map端预聚合的算子:

(1)reduceByKey

(2)aggregateByKey

(3)combineByKey

6.使用高性能算子:

(1)reduceByKey代替groupByKey

(2)使用mappartition代替map

(3)使用foreachPartitions代替foreach

(4)对大量分区过滤后使用repartition/coalesce减少分区

7.使用广播变量

如果Executor端使用到了Driver端的变量副本,如果不使用广播变量,在每个Executor端有多少个task任务就有多少个变量副本。

如果使用广播变量,Executor端的变量副本只有一份,所有的Executor端使用一份共享的变量副本。可以节省大量的内存。

8.优化数据结构

在编写Spark代码时

(1)尽量使用原生的数据类型代替字符串

(2)尽量使用字符串代替对象

(3)尽量使用数组代替map集合

(4)尽量使用tinyint代表int

9.使用Kryo序列化方式

在Spark中的序列化:

(1)在算子函数中使用到外部变量时,该变量会被序列化后进行网络传输。

(2)将自定义的类型作为RDD的

 

### 关于 Apache Spark 性能的最佳实践 #### 配置高效的执行器设置 为了使现有的 Apache Spark 作业更加高效并降低成本,在配置执行器时应考虑多个因素。合理调整执行器的数量、内存分配以及核心数可以显著提高性能和资源利用率[^1]。 #### SQL 查询中的连接策略提示 当处理涉及大量数据集之间的关联操作时,通过使用 `JOIN` 提示来指导查询计划的选择能够有效提升效率。这允许开发者指定特定类型的联接算法(如广播哈希联接),从而绕过默认的成本估算机制而获得更佳的表现效果[^2]。 #### 数据序列化优化 选择合适的数据序列化库对于减少网络传输开销至关重要。Kryo 是一种轻量级且快速的对象图序列化框架,默认情况下它提供了更好的压缩率与速度平衡;然而如果应用中有自定义类,则可能需要注册这些类型以进一步改善性能表现[^3]。 ```python from pyspark import SparkConf, SparkContext conf = (SparkConf() .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .registerKryoClasses([MyCustomClass])) sc = SparkContext(conf=conf) ``` #### 动态资源管理 启用动态分配功能可以根据实际工作负载自动增加或释放集群节点上的执行实例数量。此特性有助于最大化吞吐量的同时最小化闲置时间造成的浪费,特别是在多租户环境中尤为有用。 #### 广播变量的应用场景 当一个小表频繁参与到与其他大表的 join 操作之中时,将其作为广播变量加载到每个任务的工作进程中可避免不必要的 shuffle 过程,进而加快整个计算流程的速度。不过需要注意的是只有当小表确实很小的时候才适合这样做,因为过多占用 executor 的 JVM 堆空间反而会带来负面影响。 ```sql SELECT /*+ BROADCAST(small_table) */ ... FROM large_table JOIN small_table ON ... ``` #### 调整Shuffle行为 适当节 shuffle 文件大小 (`spark.sql.shuffle.partitions`) 可以影响分区粒度,通常更大的值意味着更高的并发度但也增加了度复杂性和额外 I/O 开支。因此找到一个合适的数值取决于具体应用场景下的权衡取舍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值