【Spark2运算效率】第四节 影响生产集群运算效率的原因之数据倾斜

【Spark2运算效率】【Spark2运算效率】第四节 影响生产集群运算效率的原因之数据倾斜

前言

当ETL调度任务所能拥有的资源能够满足其在较为资源冗余的状况下实施运算,长时间的运算过程中可能是涉及了数据倾斜的现象;数据倾斜可以说是分布式运算中不可避免的一种现象,这种现象带来的后果就是任务执行时长会随着倾斜度的增加而变长,甚至会有Fail的风险(任务重跑);
不管是任务执行延时还是任务重跑,这都在一定程度上增加了集群的运营压力,所幸的是,只要编写过程稍加注意,还是能避免很大一部分的数据倾斜事件,剩余的部分也能通过一些固定的手法进行更正解决。

倾斜实例

如图所示,在查看任务执行流程时,stage67发生了超大体量TB级别的数据输入:
在这里插入图片描述
数据倾斜带来的现象比较明显,通常是99%的task跑完后等待最后一个task的执行,在随后的stage150发生了数据倾斜,卡了2.4个小时仍未执行完成:
在这里插入图片描述
在集群资源紧张的时长,单个任务时间跨度过长可能存在响应心跳失败或者卡住的task被GC的现象,这会导致任务失败重跑,以至于在治理之前,该任务的执行时长在5-9个小时之间浮动,具体如图:
在这里插入图片描述

治理过程

由于涉及大体量数据表,因此首要是对任务submit资源进行了上调。这里特别说明:
拥有超大体量数据的表通常为分区表,在涉及进行分区表操作的任务中,首要保证的是资源充足,其次是要满足并发。
其次,如果是分区表经过查询、聚合动作后,最终写入临时表时(注意,这在开发过程中很常见,通常表现为DROP TABLE xxxxxx;CREATE TABLE xxxxxx AS 或者INSERT OVERWRITE TABLE xxxxxx AS),因为是临时表我们无需担心小文件累积的现象发生,因此,我们可以在代码段前设置spark.sql.shuffle.partition数目,来完成大体量数据的分发聚合操作,以此来提高执行效率。但如果是INSERT INTO TABLE这种追加操作,则要考虑落地小文件的累加问题。
最后,对于数据倾斜问题,通常是因为某个单一的KEY导致的数据分布不均匀,最直接的表现是在一些配置表(尤其是小表,在编写聚合逻辑的时候,开发人员往往认为左表或右表只有几十或几百行的数据,认为运算量不大,故直接进行了join聚合操作,这实际上是冒着很大风险,因为正是这种小表,才容易造成极为夸张的数据倾斜现象),比如在本job中的第一个数据倾斜点,就是因为引用了一张数据体量为74行的交易类型配置表:
在这里插入图片描述
在解决该数据倾斜点的时候,考虑SparkSQL shuffle遵行的基本规范,对该交易类型配置表进行了预处理落地,落地表继续执行原有的操作,这样的做法使得导致数据倾斜的KEY被提前筛掉,从而较为均匀的分配数据,最大化运用申请得到的资源(另一种方案是直接cache该表,然后开启广播分发该表,这样可以规避聚合操作带来的数据倾斜),那么再贴一下这一块调整前的运行时长:
在这里插入图片描述
这里贴一下stage明细,有超过5G的数据被分配到一个task上,而其他task获得的数据不足1M,由此,这个发生数据倾斜的task承担的运算量可以想象(运算量由聚合的另一张表决定):
在这里插入图片描述

调整过后,倾斜现象已经得到治理(采用预处理+cache广播的办法):
在这里插入图片描述

运行时长(这里博主已经将代码彻底打乱,这部分代码被提在前部执行):
在这里插入图片描述
采用广播的方法,该处数据倾斜点效率提升几十倍,该Job其他处的数据倾斜点均是使用:诊断-修改-测试的思路进行操作的,该任务整体运行时长最终稳定在1小时上下效率提升5-9倍:
在这里插入图片描述

结语

数据倾斜进行预判比较困难,多是在运行时刻才会显现出来,但是有超过一半的数据倾斜还是可以通过预防手段进行避免,以博主的经验和接触的业务类型来参看,起因往往都是因为一些配置表,因此可以总结出一些经验和数据倾斜的特征供大家开发时规避数据倾斜的参考:

  1. 大部分数据倾斜是由配置表引起的,在涉及交易类型tradetype、专户产品a_dim_smotype、客户类型custtype等数据量很小,代表某一种特性或特征的编写时,应做到该类小表的数据提前过滤(落地操作,目的是过滤掉引发数据倾斜的字段),若是引发数据倾斜的字段恰好是需要的,可先将聚合结果写入临时表,再将特征表进行cache操作,用该临时表与特征表进行聚合,则可避免数据倾斜。
  2. 若是进行聚合操作时,如果是涉及一些隐性的条件是不需要的,则应该对小表进行提前落地,这样可避免聚合时数据分发可能引起的数据倾斜。
  3. 可尝试多使用cache操作,具体格式如下:
    cache table table_name_1 select a,b,c,d from table_name_2;
    这样就可以正常使用table_name_1表了。
    大家在实际操作过程中如果碰到什么问题,可以下方流言交流。

跳转

目录

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值