Spark数据倾斜

数据倾斜

Task之间数据分配的非常不均匀即为数据倾斜

数据倾斜的影响

  • 个别任务耗时远高于其它任务,轻则造成系统资源的浪费,使整体应用耗时过大,不能充分发挥分布式系统并行计算的优势
  • 个别Task发生OOM,导致整体作业运行失败

数据倾斜原因

数据异常

Map Task数据倾斜,主要是数据源导致的数据倾斜

  • 数据文件压缩格式(压缩格式不可切分)
  • Kafka数据分区不均匀

Reduce task数据倾斜(重灾区,最常见):

  • Shuffle (外因)。Shuffle操作涉及到大量的磁盘、网络IO,对作业性能影响极大
  • Key分布不均 (内因)

数据倾斜如何排查?

  • 凭借经验或Web UI,找到对应的Stage;再找到对应的 Shuffle 算子

数据倾斜处理

  • 做好数据预处理

  • 过滤key中的空值

  • 消除数据源带来的数据倾斜(文件采用可切分的压缩方式

  • 数据倾斜产生的主要原因:Shuffle + key分布不均

数据倾斜有哪些现象

Executor lost、OOM、Shuffle过程出错、程序执行慢

单个Executor执行时间特别久,整体任务卡在某个阶段不能结束

正常运行的任务突然失败大多数 Task 运行正常,个别Task运行缓慢或发生OOM

处理数据倾斜的基本思路:

消除shuffle

减少shuffle过程中传输的数据

选择新的可用于聚合或join的Key(结合业务)

重新定义分区数

加盐强行打散Key

1、消除shuffle

  • Map端的join是典型的解决方案

  • 可以完全消除Shuffle,进而解决数据倾斜

  • 有很强的适用场景(大表和小表关联),典型的大表与小表的join,其他场景不合适

2、减少shuffle过程中传输的数据

  • 使用高性能算子,避免使用groupByKey,用reduceByKey或aggregateByKey替代

  • 没有从根本上解决数据分配不均的问题,收效有限,使用场景有限

3、选择新的可用于聚合或join的Key(结合业务)

  • 从业务出发,使用新的key去做聚合或join。如当前key是【省 城市 日期】,在业务允许的情况下选择新的key【省 城市 区 日期】,有可能 解决或改善 数据倾斜问题

  • 存在的问题:这样的key不好找;或者找到了新的key也不能解决问题

4、重新定义分区数,改变reduce的并行度--key.hashCode % reduce个数 = 分区号

  • 变更 reduce 的并行度。理论上分区数从 N 变为 N-1 有可能解决或改善数据倾斜

  • 一般情况下这个方法不管用,数据倾斜可能是由很多key造成的,但是建议试试因为这个方法非常简单,成本极低;可能只是解决了这一次的数据倾斜问题,非长远之计

  • 缺点:适用性不广;优点:简单

5.加盐强行打散Key

  • shuffle + key不能分散

5.1、两阶段聚合

  • 加盐打散key。给每个key都加一个随机数,如10以内的随机数。此时key就被打散了

  • 局部聚合。对打上随机数的数据,执行一次聚合操作,得到结果

  • 全局聚合。将各个key的前缀去掉,再进行一次聚合操作,得到最终结果

  • 两阶段聚合优点:

  • 对于聚合类的shuffle操作导致的数据倾斜,效果不错。通常都可以解决掉数据倾斜,至少是大幅度缓解数据倾斜,将Spark作业的性能提升数倍以上

  • 仅适用于聚合类的shuffle操作,适用范围相对较窄。如果是join类的shuffle操作,还得用其他的解决方案

5.2、采样倾斜key并拆分join操作

  • 业务场景:两个RDD/两张表进行 join 的时候,数据量都比较大

  • 使用场景:计算两个RDD/两张表中的key分布情况。如果出现数据倾斜,是其中一个RDD/Hive表中的少数几个key的数据量过大,而另一个RDD/Hive表中的所有key都分布比较均匀,那么采用这个解决方案比较合适

  • 处理步骤:

  • 1、对包含少数几个数据量过大的key的那个RDD,通过sample算子采样出一份样本来,然后统计一下每个key的数量,计算出数据量最大的是哪几个key

  • 2、将这几个key对应的数据从原来的RDD中拆分出来,形成一个单独的RDD,并给每个key都打上n以内的随机数作为前缀,而不会导致倾斜的大部分key形成另外一个RDD

  • 3、将需要join的另一个RDD,也过滤出来那几个倾斜key对应的数据并形成一个单独的RDD,将每条数据膨胀成n条数据,这n条数据都按顺序附加一个0~n的前缀,不会导致倾斜的大部分key也形成另外一个RDD

  • 4、再将附加了随机前缀的独立RDD与另一个膨胀n倍的独立RDD进行join,此时就可以将原先相同的key打散成n份,分散到多个task中去进行join了

  • 5、另外两个普通的RDD就照常join即可;

  • 6、最后将两次join的结果使用union算子合并起来即可,就是最终的join结果

5.3、使用随机前缀和扩容再进行join

  • 业务场景:如果在进行join操作时,RDD中有大量的key导致数据倾斜,进行分拆key没什么意义,此时就只能使用最后一种方案来解决问题了

  • 处理步骤:

  • 1、选一个RDD,将每条数据都打上一个n以内的随机前缀(打散)

  • 2、对另外一个RDD进行扩容,将每条数据都扩容成n条数据,扩容出来的每条数据都依次打上一个0~n的前缀

  • 3、将两个处理后的RDD进行join即可

  • 优缺点:

    • 如果两个RDD都很大,那么将RDD进行N倍的扩容显然行不通
    • 使用扩容的方式通常能缓解数据倾斜,不能彻底解决数据倾斜问题
  •  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值