spark调优

目录

1、资源调优

1.1、分配更多的资源

1.2、提高并行度

2、开发调优

2.1、RDD的重用和持久化

2.2、广播变量的使用

2.3、尽量避免使用shuffle类算子

2.4、 使用高性能的算子

2.5、使用Kryo优化序列化性能

2.6、使用fastutil优化数据格式

2.7、调节数据本地化等待时长

3、基于spark内存模型调优

3.1、spark中executor内存划分

3.2、 spark的内存模型

3.3、 任务提交脚本参考

4、shuffle相关参数调优

4.1、spark的shuffle原理

4.2、HashShuffle机制

4.3、Sort shuffle机制

4.4、Spark Shuffle参数调优

5、数据倾斜调优

5.1、据倾斜发生时的现象

5.2、数据倾斜原理

5.3、数据倾斜定位

5.4、数据倾斜原因

5.5、数据倾斜的后果

5.6、数据倾斜调优

1、资源调优
1.1、分配更多的资源
写完了一个复杂的spark作业之后,进行性能调优的时候,首先第一步,就是要来调节最优的资源配置;

(1)分配资源

executor-memory、executor-cores、driver-memory

(2)如何设置这些资源

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

(3)参数调节到多大

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。

(4)使用原则

在资源比较充足的情况下,尽可能的使用更多的计算资源,尽量去调节到最大的大小。

1.2、提高并行度
spark作业中,各个stage的task的数量,也就代表了spark作业在各个阶段stage的并行度!当分配完所能分配的最大资源了,然后对应资源去调节程序的并行度。

合理设置并行度,可以充分利用集群资源,减少每个task处理数据量,而增加性能加快运行速度。

(1)可以设置task的数量

至少设置成与spark Application 的总cpu core 数量相同。
最理想情况,150个core,分配150task,一起运行,差不多同一时间运行完毕;
官方推荐,task数量,设置成spark Application 总cpu core数量的2~3倍。

(2)设置参数spark.defalut.parallelism来设置task数量

默认是没有值的,如果设置了值为10,它会在shuffle的过程才会起作用。

可以通过在构建SparkConf对象的时候设置,例如:
   new SparkConf().set("spark.defalut.parallelism","500")

(3)给RDD重新设置partition的数量

使用rdd.repartition 来重新分区,该方法会生成一个新的rdd,使其分区数变大。一个partition对应一个task。

(4)提高sparksql运行的task数量

通过设置参数 spark.sql.shuffle.partitions, 默认为200;
可以适当增大,来提高并行度。 比如设置为 spark.sql.shuffle.partitions=500

2、开发调优
2.1、RDD的重用和持久化
(1)重用

当第一次使用rdd2做相应的算子操作得到rdd3的时候,就会从rdd1开始计算,先读取HDFS上的文件,然后对rdd1做对应的算子操作得到rdd2,再由rdd2计算之后得到rdd3。同样为了计算得到rdd4,前面的逻辑会被重新计算。
默认情况下多次对一个rdd执行算子操作,去获取不同的rdd,都会对这个rdd及之前的父rdd全部重新计算一次。

可以把多次使用到的rdd,也就是公共rdd进行持久化,避免后续需要,再次重新计算,提升效率。如图,将rdd2持久化:

(2)持久化

调用rdd的cache或者persist方法进行持久化。

cache方法默认是把数据持久化到内存中 ,例如:rdd.cache ,其本质还是调用了persist方法
persist方法中有丰富的缓存级别,这些缓存级别都定义在StorageLevel这个object中,可以结合实际的应用场景合理的设置缓存级别。
(3)持久化的时可以采用序列化

将数据持久化在内存中,那么可能会导致内存的占用过大,这样的话,也许会导致OOM内存溢出。
当纯内存无法支撑公共RDD数据完全存放的时候,就优先考虑使用序列化的方式在纯内存中存储。将RDD的每个partition的数据,序列化成一个字节数组;序列化后,大大减少内存的空间占用。
序列化在获取数据的时候,需要反序列化。但是可以减少占用的空间和便于网络传输。
可以使用双副本机制,进行持久化。
2.2、广播变量的使用


(1)广播变量引入

Spark中分布式执行的代码需要传递到各个executor的task上运行。对于一些只读、固定的数据,每次都需要Driver广播到各个Task上,这样效率低下。广播变量允许将变量只广播给各个executor。该executor上的各个task再从所在节点的BlockManager(负责管理某个executor对应的内存和磁盘上的数据)获取变量,而不是从Driver获取变量,从而提升了效率。

(2)广播变量,初始的时候,就在Drvier上有一份副本。通过在Driver把共享数据转换成广播变量。

(3)广播变量数量等于executor数量。

(4)广播变量只能在Driver端定义,不能在Executor端定义。

(5)在Driver端可以修改广播变量的值,在Executor端无法修改广播变量的值。

(6)如何使用广播变量

通过sparkContext的broadcast方法把数据转换成广播变量。

获取广播变量

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值