spark优化
代码层面
1.避免创建重复的rdd,对多次使用的rdd进行持久化,才能保证一个rdd被多次使用时只被计算一次
2.persist方法可以自己选择持久化级别
-
memory_and_disk_ser,其中_ser后缀表示使用序列化的方式来保存rdd数据,rdd中的每个partition都会被序列化成一个大的字节数组。序列化的方式可以减少持久化数据对内存/磁盘的占用量,避免内存被持久化数据占用过多而发生频繁GC
-
RDD的cache()默认是MEMORY_ONLY级别
-
DataFrame和Dataset的cache()默认级别是MEMORY_AND_DISK
-
根据rdd数据量的大小依次推荐:memory_only>memory_only_ser>memory_and_disk_ser
-
通常不建议使用disk_only和后缀为_2的级别。因为性能会很低
3.尽量避免使用shuffle类算子,比如reducebykey,join,distinct,repartitionshuffle过程中会产生大量的磁盘读写的io操作,和数据的网络传输,故性能较差
采用broadcast+map的join操作不会导致shuffle操作
4.使用map-side预聚合的shuffle操作,预聚合是指每个节点在本地对相同key先进行一次聚合操作,在进行shuffle操作。
比如使用reduceByKey来替代groupByKey
5.使用高性能算子
- 使用mapPartitions代替普通map
mapPartitions算子,一次函数调用会处理一个partition所有的数据,而不是想map算子一样,一次函数调用只处理一条。因为mapPartitions函数调用要处理一个partition所有的数据,所以可能会出现OOM的问题。 - 使用foreachPartitions代替foreach,原理类似mapPartitions
- 在filter之后进行coalesce操作,减少partition个数
6.广播大变量。sc.broadcast(list)
运行资源层面
executor的内存主要分为三块:
- task执行代码时占用,默认时executor总内存的20%
- task通过shuffle过程拉取上一个stage的task的输出后,进行聚合等操作时使用,默认也是20%
- rdd持久化时使用,默认占60%
任务执行速度和每个executor进程的cpu core数量有直接关系,一个CPU core同一时间可以执行一个task任务
这两个是spark1.6以后的内存管理参数,统一内存管理模型
--conf spark.memory.fraction=0.8 \ spark2.2中默认是0.6
--conf spark.memory.storageFraction=0.3 \ 默认是0.5
老版本的内存管理参数。静态管理模型
--conf spark.storage.memoryFraction \设置rdd持久化数据在executor内存中占的比例,默认0.6
--conf spark.shuffle.memoryFraction \设置shuffle过程聚合操作使用executor内存的比例,默认0.2
其他的一些配置
--conf spark.sql.adaptive.enabled=true \ 这个参数有点坑,会重试很多次
--conf spark.speculation=true \ 推测执行 谨慎使用,严重的会造成所有资源被全部占用,不能及时释放,默认是关闭的(启动多个相同task(备份任务)处理相同的数据块,哪个完成的早,则采用哪个task的结果)
--conf spark.speculation.multiplier=3 \ 时间比例,当task完成了75%的时候,取完成了的task的执行时间的中位数,再乘以这个时间比例,默认为1.5。当未完成的task的执行时间超过了这个乘积值,就开启推测执行。
--conf spark.default.parallelism \ 每个stage的默认task数量,只有在处理RDD时才会起作用,对Spark SQL的无效。
--conf spark.sql.shuffle.partitions 默认200,join等shuffle操作的并行度,一般会调大一些加快执行速度且避免倾斜 对sparks SQL专用的设置,对RDD无效
--conf spark.sql.autoBroadcastJoinThreshold 该参数默认为10M,在进行join等聚合操作时,将小于该值的表broadcast到每台worker,消除了大量的shuffle操作,对视图无效
--conf spark.yarn.driver.memoryOverhead 客户端模式下,每个driver分配的堆外内存(默认driverMemory * 0.10,并且不小于384m) (实时作业运行一段时间后突然挂断,可调大该参数)
--conf spark.yarn.executor.memoryOverhead 每个executor分配的堆外内存 (默认executorMemory * 0.10,并且不小于384m) (一般spark报oom时,可调大该参数)
--conf spark.task.reaper.enabled=true \ 允许监视已终止/中断的任务。
--conf spark.task.reaper.killTimeout=100s \ 设置指定超时,如果已终止的任务未停止运行,执行程序JVM将自行终止
--conf spark.default.parallelism=20 \ 设置每个stage的默认task数量
--conf spark.dynamicAllocation.enabled=false \ 关闭spark的动态资源分配,资源强管控
--conf spark.shuffle.service.enabled=true \ 启用外部随机服务。此服务保留执行程序写入的随机文件,以便可以安全地删除执行程序。如果spark.dynamicAllocation.enabled为“true”,则必须启用此选项