Spark 数据倾斜处理方案

一 什么数据倾斜

琅琊榜spark作业的倾斜判断条件是:

Spark 任务数据倾斜:任意 Stage 1)至少存在一个时间倾斜度、数据量倾斜度均大于 2 的 Task,2)且倾斜 task 中最长执行时长与 Stage 执行时长的比值大于 0.5,3)且 Stage 的执行时长超过 1800 秒

什么是时间倾斜度和数据量倾斜度?

  • 执行时间倾斜度定义为:所有并行节点执行时长的最大值 (Max) 与中位数 (Median) 的比值;
  • 数据量倾斜度定义为:所有并行节点所分配的数据量的最大值 (Max) 与中位数 (Median) 的比值;

倾斜stage体现为:
执行时间和数据量倾斜

这里数据倾斜需要和慢节点区分开来,慢节点也会看到某些task的执行时长很长,但是慢节点数据量倾斜度一般来说不满足数据倾斜的条件。而且慢节点的重试任务会执行的比较快;

二 场景和治理手段

场景治理手段
读取HIVE原始log日志表的时候出现了数据倾斜大文件切割
在大表关联小表过程中出现了数据倾斜使用广播关联
在两个大表JOIN过程中出现了数据倾斜具体情况具体分析

1 读文件倾斜

执行引擎解决办法参数解释
spark2spark.hadoop.hive.exec.orc.split.strategy=ETLspark2的情况下读取ORC文件时由参数spark.hadoop.hive.exec.orc.split.strategy控制读取ORC表时生成split的策略。BI策略以文件为粒度进行split划分;ETL策略会将文件进行切分,多个stripe组成一个split;HYBRID策略为:当文件的平均大小大于hadoop最大split值(默认256 * 1024 * 1024)时使用ETL策略,否则使用BI策略。默认情况下使用的策略是HYBRID,但是有些情况下总体平均文件大小较小,但是个别文件的大小比较大时,使用HYBRID默认不会切分这些大文件。因此需要改成ETL策略。
spark3spark.sql.files.splitSingleFileByHiveStrategy=falsespark3提供了新的参数spark.sql.files.splitSingleFileByHiveStrategy,该参数默认值为true,即follow spark2的读取ORC策略。建议改成false,默认切割大文件。

2 大表关联小表

解决方案1:添加map join hint

解决方案2:添加参数 set spark.sql.statistics.fallBackToHdfs=true;
参数解释:当表的文件大小元数据信息不可能用时回退到hdfs计算表的文件大小,从而决定是否使用map join

3 大表关联大表

场景1:倾斜key为无效热key,如null、NA 等

解决办法:因此可以找表中离散程度较大的字段进行hash化,并拼接一些特殊字符串作为关联键。将关联条件从a.item_id = sku.sku_id改成case when length(a.item_id)>8 then a.item_id else concat(‘rand_’,abs(hash(a.event_timestamp))) end = sku.sku_id

场景2:倾斜key无固定值,可能为爬虫数据等等

解决办法1(维表扩容法):将B表的每一条记录通过复制成10条(视倾斜状况而定,可以提高倍数),分别标记成第0-9位次。在A表进行关联时,除了原有的关联键,还需额外生产一个可以随机生成10以内数字的关联键(找表中离散程度较大的字段进行hash化,并且摸10取余数即可),将和B表的位次进行关联

解决办法2(两段关联法): 首先生成一个将A表按照关联键进行group by取每个关联键的count值,得到count值较大的TOP记录临时表,这样我们就能确定倾斜的key了。将B表的内容划分两部分,一部分是B1包括确定倾斜的倾斜数据,一部分是B2包括非倾斜的数据。将A对B的关联改成 A和B1的广播关联,然后再和B2进行关联,在和B2关联的时候判断A的内容如果已经和B1关联上了,则将A的关联键进行打散,找表中离散程度较大的字段进行hash化,并拼接一些特殊字符串作为关联键

解决办法3(AQE):使用AQE
关于AQE的参数做下介绍:

参数默认值解释
spark.sql.adaptive.enabledfalse是否开启动态执行计划,如果需要开启AQE的倾斜处理功能,则这个参数必须为true
spark.sql.adaptive.skewJoin.enabledtrue是否开启动态调整倾斜功能
spark.sql.adaptive.skewJoin.skewedPartitionFactor5只有当一个分区的大小 > 所有分区大小中位数乘以spark.sql.adaptive.skewJoin.skewedPartitionFactor时才认为是倾斜的分区
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes256MB当一个分区的大小超过spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes大小时,才被认为是倾斜
spark.shuffle.accurateBlockThreshold100M在使用MapStatus的压缩时,shuffle block的大小超过该值时才会被准确记录,如果小于该值,Mapstatus的信息将会被一个平均值填充。即会影响到partition是否倾斜判断。注意只有没有开启RSS的作业才会用到这个参数
spark.shuffle.minNumPartitionsToHighlyCompress2000当分区大小超过多少时,会使用MapStatus的压缩,即所有小于 spark.shuffle.accurateBlockThreshold(默认100M)的值都会被一个平均值所代替填充。即会影响到partition是否倾斜判断。注意只有没有开启RSS的作业才会用到这个参数

开启AQE:

如果使用AQE的话,将spark.sql.adaptive.enabled参数置为true,结合琅琊榜中判断数据倾斜度来看,建议设置spark.sql.adaptive.skewJoin.skewedPartitionFactor=2。另外如果作业属于非RSS作业时,并且shuffle partition分区的大小超过默认值2000时,记得调整spark.shuffle.minNumPartitionsToHighlyCompress的大小,并且适当增加driver的memory大小。

如何判断AQE已经生效:

可以查看在sparkUI上查看任务的DAG图,如果AQE已经成功处理数据倾斜则会在DAG的SortMergeJoin节点显示skew=true,并且在UI的物理执行计划树中显示倾斜的分区数和最大倾斜的分区、最小倾斜的分区的大小
在这里插入图片描述
在这里插入图片描述

不能使用AQE的场景:https://mp.weixin.qq.com/s/B3WFMZjOotpET90nfrE-GQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值