Spark参数调优经典实战

一:常用调优参数

#配置文件,使用这个名称application.conf就可以自动读取
#以下是spark的调优参数

#自动广播
spark.sql.autoBroadcastJoinThreshold="10485760"
#spark sql shuffle并行度设置
spark.sql.shuffle.partitions="200"
#自动广播超时时间
#spark.sql.broadcastTimeout=""
#是否启动shuffle压缩
spark.shuffle.compress="true"
#shuffle失败重试次数
spark.shuffle.io.maxRetries="5"
#shuffle重试的间隔时间
spark.shuffle.io.retryWait="10s"
#广播是否启动压缩
spark.broadcast.compress="true"
#序列化机制
spark.serializer="org.apache.spark.serializer.KryoSerializer"
#存储与执行的内存比例
spark.memory.fraction="0.6"
#存储的内存比例
spark.memory.storageFraction="0.5"
#spark core shuffle并行度设置
spark.default.parallelism=200
#数据本地化等待时间
spark.locality.wait="3s"
#是否启动推测机制
spark.speculation.flag="true"
#推测机制启动时机
spark.speculation.multiplier="1.5"

二:常用优化方式介绍

1.:增加分配资源

1.executor-memory
2.executor-cores
3.num-executor
4.driver-memory

在实际的生产环境中,提交spark任务时,使用spark‐submit shell脚本,在里面调整对应的参数。
提交任务的脚本: spark‐submit \
‐‐master spark://node1:7077 \
‐‐class cn.itcast.WordCount \
‐‐num‐executors 3 \
配置executor的数量
‐‐driver‐memory 1g \
配置driver的内存(影响不大)
‐‐executor‐memory 1g
配置每一个executor的内存大小
‐‐executor‐cores 3 \
配置每一个executor的cpu个数
/export/servers/wordcount.jar

参数调到多大合适?
第一种情况:standalone模式 先计算出公司spark集群上的所有资源 每台节点的内存大小和cpu核数,
比如:一共有20台worker节点,每台节点8g内存,10个cpu。
实际任务在给定资源的时候,可以给20个executor、每个executor的内存8g、每个executor的使用的cpu个数 10。
第二种情况:Yarn 先计算出yarn集群的所有大小,比如一共500g内存,100个cpu;
这个时候可以分配的大资源,比如给定50个executor、每个executor的内存大小10g,每个executor使用的cpu 个数为2。
使用原则:你能使用的资源有多大,就尽量去调节到大的大小(executor的数量:几十个到上百个不等;executor的 内存;exector的cpu个数)

2.提高并行度

并行度的设置原则:
1.至少需要设置为cpu的核数 = task的个数,这样保证不浪费资源,但是问题还有:就是当有的task执行快,其他的执行慢,就会造成执行快的task中的资源空闲下来,也会浪费
2.设置为cpu核数的2~3倍最理想,保证资源充分利用

如何设置?

#spark sql shuffle并行度设置
spark.sql.shuffle.partitions="200"

#spark core shuffle并行度设置
spark.default.parallelism=200

这两种设置方式分别是提高sql和core的并行度,默认都是200,根据数据量可以设置到500或以上

3.RDD重用(公共rdd持久化)

原因:
由于RDD是惰性求值,每次执行Action算子,都会从开始的RDD执行,知道末尾RDD,求得数据

RDD重用原理如何进行持久化?

     1.rdd.cache 默认方式就是MEMORY_ONLY
     2.rdd.persist(StorageLevel.MEMORY_ONLY) 可以根据业务需要进行存储级别的设置

如何持久化同时进行序列化?
(1)如果正常将数据持久化在内存中,那么可能会导致内存的占用过大,这样的话,也许会导致OOM内存溢出。
(2)当纯内存无法支撑公共RDD数据完全存放的时候,就优先考虑使用序列化的方式在纯内存中存储。将RDD的每个 partition的数据,序列化成一个字节数组;序列化后,大大减少内存的空间占用。
(3)序列化的方式,唯一的缺点就是,在获取数据的时候,需要反序列化。但是可以减少占用的空间和便于网络传输
(4)如果序列化纯内存方式,还是导致OOM,内存溢出;就只能考虑磁盘的方式,内存+磁盘的普通方式(无序列化)。
(5)为了数据的高可靠性,而且内存充足,可以使用双副本机制,进行持久化 持久化的双副本机制,持久化后的一个副本,因为机器宕机了,副本丢了,就还是得重新计算一次;
持久化的每个数据单元,存储一份副本,放在其他节点上面,从而进行容错;
一个副本丢了,不用重新计算,还可以使用另外一份副本。这种方式,仅仅针对你的内存资源极度充足。
比如: StorageLevel.MEMORY_ONLY_2

4.广播变量

为何进行广播变量?
1.广播前 ,100 个task需要拉取100次共享数据
2.广播后,每个executor只需要一份数据,而每个executor中有多个task,减少共享数据的IO次数
广播变量的使用场景:
1.小表join大表的时候,把小表广播出去
2.多个task使用共享数据的时候,把共享数据广播出去

如何进行广播?
1.SparkCore:
spark.sparkcontext.broadcast(需要广播的数据)
2.SparkSQL
1.先设置广播小表的容量设置,默认10M大小,实际工作中可以设置为2-3G,前提是把Driver的内存设置5-10G,否则无法存储

#自动广播
spark.sql.autoBroadcastJoinThreshold="10485760"

#自动广播超时时间
#spark.sql.broadcastTimeout=""

#广播是否启动压缩
spark.broadcast.compress="true"

2.代码设置保证广播设置的有效实施,否则就算设置了自动广播也不一定就会进行广播

spark.sql(" cache table  小表名称")

5.使用Kryo进行序列化

为什么要是有Kryo进行序列化?
因为在处理数据的时候需要进行网络传输,而网络IO必然浪费大量资源,高效的序列化手段有效减少内存占比,和资源消耗
所以,Kryo的序列化机制比Java的序列化机制高效,数据只有java的1/10,所以更加适合

如何启动Kryo的序列化?

#序列化机制
spark.serializer="org.apache.spark.serializer.KryoSerializer"

Kryo序列化机制,一旦启用以后,会生效的几个地方:
(1)算子函数中使用到的外部变量
算子中的外部变量可能来着与driver需要涉及到网络传输,就需要用到序列化。
终可以优化网络传输的性能,优化集群中内存的占用和消耗
(2)持久化RDD时进行序列化,StorageLevel.MEMORY_ONLY_SER
将rdd持久化时,对应的存储级别里,需要用到序列化。
终可以优化内存的占用和消耗;持久化RDD占用的内存越少,task执行的时候,创建的对象,就不至于频繁 的占满内存,频繁发生GC。
(3) 产生shuffle的地方,也就是宽依赖
下游的stage中的task,拉取上游stage中的task产生的结果数据,跨网络传输,需要用到序列化。
终可以优化网络传输的性

6.数据本地化等待时间

数据本地化的四个级别:
(1)PROCESS_LOCAL:进程本地化 代码和数据在同一个进程中,也就是在同一个executor中;计算数据的task由executor执行,数据在executor的 BlockManager中;性能好
(2)NODE_LOCAL:节点本地化 代码和数据在同一个节点中;比如说数据作为一个HDFS block块,就在节点上,而task在节点上某个executor中 运行;或者是数据和task在一个节点上的不同executor中;数据需要在进程间进行传输;性能其次
(3)RACK_LOCAL:机架本地化 数据和task在一个机架的两个节点上;数据需要通过网络在节点之间进行传输; 性能比较差
(4) ANY:无限制 数据和task可能在集群中的任何地方,而且不在一个机架中;性能差
数据本地化级别如何设置本地等待时长?

#1.数据本地化等待时间,默认3秒
spark.locality.wait="3s"
这种方式最常用,可以根据进程本地化-->节点本地化-->机架本地化-->无限制 如果超过等待时长就依次类推,执行最高效的本地化


#2.另外还有指定本地位置的等待时长
spark.locality.wait.node
spark.locality.wait.process
spark.locality.wait.rack

注:
     两种方式不可同时使用  
     别为了本地化而耗费太多的等待时长,本末倒置,如果数据量比较大的时候可以设置到5-8
7.内存调优

1.spark内存参数调整
executor内存机制如何调整?

#存储与执行的内存比例
spark.memory.fraction="0.6"

#存储的内存比例
spark.memory.storageFraction="0.5":
     如果在界面看到GC时长特别长,说明存储对象空间太小,为了腾空间而触发了GC的执行
     这时候就可以调高内存executor-memory 或者调高执行区的与存储区的内存比例,同时也可以调小存储区的内存占比

2.JVM的内存机制,为什么会触发GC?
GC的触发原理如果在GC的时候造成拉取数据失败怎么办?
重试,如何重试?

#shuffle失败重试次数
spark.shuffle.io.maxRetries="5"

#shuffle重试的间隔时间
spark.shuffle.io.retryWait="10s"

8.启动推测机制

为什么要开启推测机制?
因为任务执行过程可能有的任务在执行过程中会发生异常,导致执行时间大大增加
推测机制根据这种情况开启另外一个任务去执行相同的任务,最终以最早执行完成的任务的数据为结果数据
避免无限等待任务的执行时长

如何开启?

#是否启动推测机制
spark.speculation.flag="true"

#推测机制启动时机
spark.speculation.multiplier="1.5"

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在进行Spark参数调优时,我们可以考虑以下几个主要参数: 1. num-executors:该参数用于设置Executor的数量。在Spark 1.6之前,它还用于设置RDD持久化数据在Executor内存中所占的比例,默认为0.6。可以根据作业中需要持久化的RDD数量来调整该参数值。如果作业中有较多的RDD需要进行持久化操作,可以将该参数值调高;如果作业中只有少量的RDD需要进行持久化操作,可以将该参数值调低。\[2\] 2. Spark.Shuffle.memoryFraction:该参数用于设置Driver进程的内存。通常情况下,我们不需要显式地设置该参数,因为Driver运行内存的默认值为512MB。但是,当使用collect算子时,需要确保Driver内存足够大,以避免出现内存溢出的错误。一般建议将Driver内存设置为1G~4G。\[3\] 3. Spark.default.parallelism:该参数用于设置默认的并行度。并行度决定了作业中任务的并发执行程度。默认情况下,Spark会根据集群的总核数来自动设置并行度。但是,如果需要手动设置并行度,可以调整该参数的值。一般建议将并行度设置为集群的总核数的2~3倍。\[1\] 通过调整这些参数,我们可以优化资源使用率,提升Spark作业的执行性能。请根据实际情况和需求进行参数调优。 #### 引用[.reference_title] - *1* *2* *3* [Spark性能调优](https://blog.csdn.net/aikeaidecxy/article/details/126491521)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值