Spark数据倾斜和调优

一、哪些情况会产生数据倾斜以及解决方案
在分布式计算中,数据倾斜是指数据在分布式节点中的不平衡分布,导致某些节点的负载过重,从而影响整个任务的运行效率和性能。对于Spark来说,数据倾斜是一个常见的问题,可能会导致任务运行时间过长、资源浪费、节点宕机等问题。
1、shuffle的时候,如果这个时候shuffle的字段为空,会出现数据倾斜。
解决方案:将空字段进行过滤
2、key有很多,分区设置过少,导致很多key聚集在一个分区出现的数据倾斜
解决方案:局部聚合 + 全局聚合
局部聚合–> 将分组字段的值加上一个随机数[加盐]
3、当某一个表中某一个key数据特别多,然后使用group by就会出现数据倾斜
解决方案:将小表广播出去,有原来的reduce join 变成 map join ,避免shuffle操作,从而解决数据倾斜
4、大表 join 小表 ,这两个表中有某一个key或者几个key数据比较多,会出现数据倾斜
5、大表 join 大表 ,其中某一个表分布比较均匀,另个一表存在某一个或者某几个key数据特别多也会出现数据倾斜
解决方案:将容易产生数据倾斜的key过滤出来,单独处理[加盐]扩容;没有数据倾斜的key的数据照常处理(如果导致倾斜key特别多的话,比如成千上万个key都导致数据倾斜,这种方法就不适用了,需要结合其它方法一起解决)
6、大表 join 大表 ,其中某一个表分布比较均匀,另一个表存在很多key数据特别多,也会出现数据倾斜
解决方案:直接将产生数据倾斜的表进行加盐[0-9],对另一个表进行扩容[最多扩容10倍]
二、缺失值处理
缺失值处理有两种方式,丢弃和填充
1、什么是缺失值,列的值为NaN、null、" “、”,“、“Null” 等等
2、缺失值处理的框架:df.na
3、缺失值处理
删除:API df.na.drop()
删除策略 any 只要一行中有一列值为NaN就删除该行 ;all 一行中所有的列值全部为NaN才删除;针对指定列删除 df.na,drop(“any”,List(“列名1”,“列名2”)),一行的列名1和列名2这两列有一列数据为NaN,就删除改行
填充 API df.na.fill(”")
替换 API df.na.repelace(“列名”,Map(“列值”,“替换值”))
三、调优
1、增加资源(shell提交任务时候资源调整)
executor-memory 每个executor内存大小
executor-cores 每个executor使用的CPU核数
num-executor 启动的executor的数量

/usr/local/spark-current/bin/spark-submit \
--master yarn \
--deploy-mode client \
--executor-memory 2G \
--driver-memory 1G \
--queue root.default \
--class my.Application \
--conf spark.ui.port=4052 \
--conf spark.port.maxRetries=100 \
--num-executors 2 \
--jars test1-spark-connector_2.11-2.3.1.jar \
--conf spark.memory.fraction=0.6 \

2、增加并行度
spark core spark.default.parallelism
sparksql spark.sql.shuffle.partitions
3、广播变量
spark core spark.sparkcontext.broadcast
spark sql spark.sql.autoBroadcastJoinThreshold 要广播出去的小表限制
4、RDD的重用
缓存persist或Cache
5、调整内存占比
spark.memory.fraction
spark.memory.storageFraction
spark.shuffle.io.maxRetries
spark.shuffle.io.retryWait

6、推测机制
spark.speculation
spark.speculation.multiplier

7、补充 Spark GC
内存分为两块(青年代和老年代)
青年代中又分为三块(Eden、survivor0、survivor1)
Eden中存放的是初始化对象,随着时间推移,这一块区域满了以后会进行minor GC,不用的清楚掉,然后使用的放到survivor0 中
Eden中清空以后又可以存放对象了,然后再次存满以后再次GC,直到survivor0中也满了,GC会 把Eden和survive0中使用的对象放在survive1中,不用的清除
重复这个步骤
Survive1中也存储满了以后,会把使用的对象放在老年代中,不使用的清除掉
当老年代中也存满了以后,这个时候就会进行full GC ,这个时候时间短几分钟,长的话十几分钟, 在这个过程中会暂停一切操作,优先GC,这个时候可能会出现拉取shuffle数据失败

应用行为属性名默认值属性描述
driver行为spark.driver.cores1driver程序运行需要的cpu内核数
driver行为spark.driver.maxResultSize1G每个Spark action(如collect)所有分区的序列化结果的总大小限制。设置的值应该不小于1m,0代表没有限制。如果总大小超过这个限制,程序将会终止。大的限制值可能导致driver出现内存溢出错误(依赖于spark.driver.memory和JVM中对象的内存消耗)
driver行为spark.driver.memory1Gdriver进程使用的内存数
driver行为spark.driver.memoryOverheaddriverMemory * 0.10,with minimum of 384driver端分配的堆外内存
driver行为spark.driver.extraClassPathNone附加到driver的classpath的额外的classpath实体
driver行为spark.driver.defaultJavaOptionsNone默认传递给driver的JVM选项字符串。注意这个配置不能直接在代码中使用SparkConf来设置,因为这个时候driver JVM已经启动了,可以在命令行通过–driver-java-options参数来设置
driver行为spark.driver.extraJavaOptionsNone传递给driver的JVM选项字符串
driver行为spark.driver.extraLibraryPathNone指定启动driver的JVM时用到的库路径。注意,在这个选项中设置Spark属性或者堆大小是不合法的。Spark属性需要用–driver-class-path设置
driver行为spark.driver.userClassPathFirstfalse当在driver中加载类时,是否用户添加的jar比Spark自己的jar优先级高。
executor行为spark.executor.memory1G每个executor进程使用的内存数
executor行为spark.executor.memoryOverheadexecutorMemory * 0.10, with minimum of 384xecutor JVM堆外内存设置,用于解决JVM开销,内部字符串,其他本机开销等问题
executor行为spark.executor.extraClassPathNone附加到executors的classpath的额外的classpath实体,一般不用
executor行为spark.executor.defaultJavaOptionsNone默认的JVM选项,以附加到spark.executor.extraJavaOptions
executor行为spark.executor.extraJavaOptionsNone传递给executors的JVM选项字符串。例如GC设置或者其它日志设置。注意,在这个选项中设置Spark属性或者堆大小是不合法的。Spark属性需要用SparkConf对象或者spark-submit脚本用到的spark-defaults.conf文件设置。堆内存可以通过spark.executor.memory设置
executor行为spark.executor.extraLibraryPathNone指定启动executor的JVM时用到的库路径
executor行为spark.executor.userClassPathFirstfalse与spark.driver.userClassPathFirst相同的功能
executor行为spark.executor.cores1每个executor使用的核数
executor行为spark.default.parallelism本地模式:机器核数;Mesos:8;其他:max(executor的core,2)默认并行度
shuffle行为spark.reducer.maxSizeInFlight48m从每个reduce中获取的最大容量,该参数值如果过低时,会导致Shuffle过程中产生的数据溢出到磁盘
shuffle行为spark.reducer.maxReqsInFlightInt.MaxValue此配置限制了获取块的远程请求的数量
shuffle行为spark.reducer.maxBlocksInFlightPerAddressInt.MaxValue该配置限制了reduce任务从其他机器获取远程块的数量
shuffle行为spark.shuffle.compresstrue是否压缩map操作的输出文件
shuffle行为spark.shuffle.file.buffer32k每个shuffle文件输出缓存的大小
shuffle行为spark.shuffle.io.maxRetries3(Netty only)自动重试次数
shuffle行为spark.shuffle.io.numConnectionsPerPeer1(Netty only)机器之间的连接复用
shuffle行为spark.shuffle.io.preferDirectBufstrue(Netty only)直接堆外内存,用于减少随机和高速缓存块传输期间的GC
shuffle行为spark.shuffle.io.retryWait5s(Netty only)重试提取之间要等待多长时间;默认情况下重试导致的最大延迟为15s
shuffle行为spark.shuffle.service.enabledfalse启用外部shuffle服务
shuffle行为spark.shuffle.service.index.cache.size100m缓存条目限制为指定的内存占用,以字节为单位
shuffle行为spark.shuffle.sort.bypassMergeThreshold200如果shuffle map task的数量小于这个阀值200,且不是聚合类的shuffle算子(比如reduceByKey),则不会进行排序
shuffle行为spark.shuffle.spill.compresstrue在shuffle时,是否将spilling的数据压缩。压缩算法通过spark.io.compression.codec指定
shuffle行为spark.shuffle.accurateBlockThreshold100 * 1024 * 1024高于该阈值时,HighlyCompressedMapStatus中的混洗块的大小将被准确记录。通过避免在获取随机块时低估随机块的大小,有助于防止OOM
shuffle行为spark.shuffle.registration.timeout5000注册到外部shuffle服务的超时时间
shuffle行为spark.shuffle.registration.maxAttempts3注册到外部shuffle服务的重试次数
压缩序列化spark.broadcast.compresstrue是否压缩广播变量
压缩序列化spark.checkpoint.compressfalse是否开启RDD压缩checkpoint
压缩序列化spark.io.compression.codeclz4RDD压缩方式org.apache.spark.io.LZ4CompressionCodec, org.apache.spark.io.LZFCompressionCodec, org.apache.spark.io.SnappyCompressionCodec, and org.apache.spark.io.ZStdCompressionCodec.
压缩序列化spark.io.compression.lz4.blockSize32kLZ4压缩中使用的块大小
压缩序列化spark.io.compression.snappy.blockSize32kSnappy压缩中使用的块大小
压缩序列化spark.kryo.classesToRegisterNone如果你用Kryo序列化,给定的用逗号分隔的自定义类名列表表示要注册的类
压缩序列化spark.kryo.registratorNone如果你用Kryo序列化,设置这个类去注册你的自定义类。如果你需要用自定义的方式注册你的类,那么这个属性是有用的。否则spark.kryo.classesToRegister会更简单。它应该设置一个继承自KryoRegistrator的类
压缩序列化spark.kryo.registrationRequiredfalse是否需要注册为Kyro可用
压缩序列化spark.kryoserializer.buffer.max64mKryo序列化缓存允许的最大值
压缩序列化spark.kryoserializer.buffer64kKyro序列化缓存的大小
压缩序列化spark.rdd.compressFalse是否压缩序列化的RDD分区
压缩序列化spark.serializerorg.apache.spark.serializer.JavaSerializer序列化对象使用的类
动态分配spark.dynamicAllocation.enabledfalse是否开启动态分配
动态分配spark.dynamicAllocation.executorIdleTimeout60s当某个executor空间超过该值时,则会remove掉该executor
动态分配spark.dynamicAllocation.cachedExecutorIdleTimeoutinfinity当executor内有缓存数据并且空闲了该值后,则remove掉该executor
动态分配spark.dynamicAllocation.initialExecutorsspark.dynamicAllocation.minExecutors初始executor数量,默认和executor数量一样
动态分配spark.dynamicAllocation.maxExecutorsinfinityexecutor上限,默认无限制
动态分配spark.dynamicAllocation.minExecutors0executor下限,默认是0个
动态分配spark.dynamicAllocation.executorAllocationRatio1默认情况下,动态分配将要求足够的执行者根据要处理的任务数量最大化并行性。虽然这可以最大程度地减少作业的等待时间,但是对于小型任务,此设置可能会由于执行程序分配开销而浪费大量资源,因为某些执行程序甚至可能无法执行任何工作。此设置允许设置一个比率,该比率将用于减少执行程序的数量。完全并行。默认为1.0以提供最大的并行度。0.5将执行者的目标数量除以2由dynamicAllocation计算的执行者的目标数量仍然可以被spark.dynamicAllocation.minExecutors和spark.dynamicAllocation.maxExecutors设置覆盖
动态分配spark.dynamicAllocation.schedulerBacklogTimeout1如果启用了动态分配,并且有待解决的任务积压的时间超过了此期限,则将请求新的执行者。
动态分配spark.dynamicAllocation.sustainedSchedulerBacklogTimeoutschedulerBacklogTimeout与spark.dynamicAllocation.schedulerBacklogTimeout相同,但仅用于后续执行程序请求
动态分配spark.dynamicAllocation.shuffleTracking.enabledfalse实验功能。为执行程序启用随机文件跟踪,从而无需外部随机服务即可动态分配。此选项将尝试保持为活动作业存储随机数据的执行程序
动态分配spark.dynamicAllocation.shuffleTracking.timeoutinfinity启用随机跟踪时,控制保存随机数据的执行程序的超时。默认值意味着Spark将依靠垃圾回收中的shuffle来释放执行程序。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spark数据倾斜调优是指使用各种技术方案解决不同类型的数据倾斜问题,以提高Spark作业的性能。数据倾斜调优的目的是解决数据倾斜带来的性能问题。 在数据倾斜发生时,常见的现象包括某些任务运行时间过长、资源利用不均衡等。为了解决这些问题,可以采取不同的方案进行调优。 对于聚合类的shuffle操作导致的数据倾斜,可以采用一些方案进行处理。其中,一种方案是使用随机前缀进行数据重分区,即在数据倾斜的key上添加一个随机前缀,将数据均匀分散到不同的分区中。这样可以有效地解决数据倾斜问题,并提高Spark作业的性能。 对于join操作导致的数据倾斜,可以采用另一种方案进行处理。该方案是使用广播变量将小表数据复制到每个Executor上,在Executor端进行join操作,从而避免shuffle过程,进而解决数据倾斜问题。这种方案非常有效,因为根本不会发生shuffle,也就不会出现数据倾斜现象。 综上所述,Spark数据倾斜调优可以通过使用不同的方案解决不同类型的数据倾斜问题,从而提高Spark作业的性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Spark性能优化指南](https://blog.csdn.net/qq_36951116/article/details/113448763)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值