Spark 系列(九) Spark数据倾斜之六大使用场景---真正详细得数据倾斜实战套路!!

写在前面: 我是「nicedays」,一枚喜爱做特效,听音乐,分享技术大数据开发猿。这名字是来自world order乐队的一首HAVE A NICE DAY。如今,走到现在很多坎坷和不顺,如今终于明白nice day是需要自己赋予的。
白驹过隙,时光荏苒,珍惜当下~~
写博客一方面是对自己学习的一点点总结及记录,另一方面则是希望能够帮助更多对大数据感兴趣的朋友。如果你也对 大数据与机器学习感兴趣,可以关注我的动态 https://blog.csdn.net/qq_35050438,让我们一起挖掘数据与人工智能的价值~

Spark数据倾斜六大使用场景:

一:倾斜表现:

  • executor lost,OOM,shuffle过程出错
  • driver oom
  • 单个executor执行时间特别久,整体任务卡在某个阶段不能结束
  • 正常运行的任务突然失败

二:倾斜产生原因:

一般都是shuffle过程中产生

  • key分布不均匀
  • 建表时考虑不周
  • 业务数据激增

三:解决数据倾斜思路:

方案一:Hive ETL预处理数据
实现思路:

并没有本质解决数据倾斜,只是让数据倾斜的发送提前HiveETL上,提前进行离线shuffle。

应用场景:

系统主要是允许用户通过Java Web系统提交数据分析统计任务,后端通过Java提交Spark作业进行数据分析统计。
要求 Spark 作业速度必须要快,尽量在 10 分钟以内,否则速度太慢,用户体验会很差。所以我们将有些 Spark 作业的 shuffle 操作提前到了 Hive ETL 中,从而让 Spark 直接使用预处理的 Hive 中间表,尽可能地减少 Spark 的 shuffle 操作,大幅度提升了性能,将部分作业的性能提升了 6 倍以上.

方案二:过滤倾斜数据

当少量key重复次数特别多时,考虑到该key是否有用处,无用可以直接filter

实现思路:

动态的sample算子对RDD采样,对数据量最多的key,用sparksql的where或者RDD的filter过滤掉。

应用场景:

有一次发现某一天 Spark 作业在运行的时候突然 OOM 了,追查之后发现,是 Hive 表中的某一个 key 在那天数据异常,导致数据量暴增。因此就采取每次执行前先进行采样,计算出样本中数据量最大的几个 key 之后,直
接在程序中将那些 key 给过滤掉。

方案三:提高shuffle操作的并行度:

最简单的方案

实现思路:

给reduceByKey(1000)多设置并行参数,默认是200,对于很多场景都太小了。

应用场景:

该方案通常无法彻底解决数据倾斜,因为如果出现一些极端情况,比如某个 key 对应的数据量有 100 万,那么无论你的 task 数量增加到多少,这个对应着 100 万数据的 key 肯定还是会分配到一个 task 中去处理,因此注定还是会发生数据倾斜的。所以这种方案只能说是在发现数据倾斜时尝试使用的第一种手段,尝试去用最简单的方法缓解数据倾斜而已,或者是和其他方案结合起来使用

方案三:引入随机数–两段聚合

groupby分组时,同值key被分到同组,在一个task上运行,此时同组某key明显多于其他组,造成的数据倾斜。

实现思路:

对该key值增加随机数或者hash加盐,使同组key刚开始groupby时被均匀分到多个task运行先进行一次聚合操作,然后再将随机数去除,使得原本key值再次分到同一组,此时key值由于上一轮的聚合,数量变得少了很多,然后再二次聚合

应用场景:

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

方案四:将reduce join 转为map join

在对 RDD 使用 join 类操作,或者是在 Spark SQL 中使用 join 语句时,而且 join 操作中的一个 RDD 或表的数据量比较小(比如几百 M 或者一两 G),

实现思路:

不使用 join 算子进行连接操作,而使用 Broadcast 变量与 map 类算子实现 join 操作,进而完全规避掉 shuffle 类的操作,彻底避免数据倾斜的发生和出现。将较小 RDD 中的数据直接通过 collect 算子拉取到 Driver 端的内存中来,然后对其创建一个 Broadcast 变量,广播给其他 Executor 节点;

接着对另外一个 RDD 执行 map 类算子,在算子函数内,从 Broadcast 变量中获取较小RDD 的全量数据,与当前 RDD 的每一条数据按照连接 key 进行比对,如果连接 key 相同的话,那么就将两个 RDD 的数据用你需要的方式连接起来。

应用场景:

适用场景较少,因为这个方案只适用于一个大表和一个小表的情况。毕竟我们需要将小表进行广播,此时会比较消耗内存资源,driver 和每个 Executor 内存中都会驻留一份小 RDD 的全量数据。如果我们广播出去的 RDD 数据比较大,比如 10G 以上,那么就可能发生内存溢出了。因此并不适合两个都是大表的情况。

方案五:采样倾斜key并拆分join操作

如果两个表数据量都很大呢,没有办法是用map join操作,那么观察两张表,如果一张表得少数key数据量过大,而另一张所有key分布均匀。

实现思路:

对少数几个数据量过大得key的RDD,通过sample算子采样,统计每个key的数量,找出数据量最大的几个key。

当这几个key对应得数据从原来得RDD中拆分出来,形成一个单独得RDD,给每个key都打上n以内随机数作为前缀。

同时把另一个需要join得RDD也过滤出来那几个key形成单独得RDD,将每条数据膨胀成n条,每个n条数据都按顺序加上0-n得前缀。

将附加了随机前缀的独立 RDD 与另一个膨胀 n 倍的独立 RDD 进行 join,此时就可以将原先相同的 key 打散成 n 份,分散到多个 task 中去进行 join 了。
而另外两个普通的 RDD 就照常 join 即可。
最后将两次 join 的结果使用 union 算子合并起来即可,就是最终的 join 结果

应用场景:

优点:对于 join 导致的数据倾斜,如果只是某几个 key 导致了倾斜,采用该方式可以用最有效的方式打散 key 进行 join。而且只需要针对少数倾斜 key 对应的数据进行扩容 n 倍。

不需要对全量数据进行扩容。避免了占用过多内存。
缺点:如果导致倾斜的 key 特别多的话,比如成千上万个 key 都导致数据倾斜,那么这种方式也不适合。

方案六:使用随机前缀和扩容RDD进行join

如果join操作,RDD中有大量得key导致数据倾斜

实现思路:

同理,先sample查看有哪些key数据量过大,发现有很多key都超过了万条数据。

将倾斜得RDD每条数据打上一个n以内得随机前缀。

同时对另一个RDD进行扩容,将每条数据都扩容成n条数据,扩容出来每条数据都依次打上0-n得前缀。

最后将两个处理后的 RDD 进行 join 即可

应用场景:

优点:对 join 类型的数据倾斜基本都可以处理,而且效果也相对比较显著,性能提升效果非常不错。

缺点:该方案更多的是缓解数据倾斜,而不是彻底避免数据倾斜。而且需要对整个 RDD进行扩容,对内存资源要求很高。

Spark系列文章目录

Spark系列(一)Spark简介与架构以及Spark安装流程(单机版和分布式版)—轻松上手Spark流处理

Spark系列(二)结构化API–DataFrame常见的业务操作

Spark系列(三)更快一点–Spark运行处理数据原理,如何简单提高并行度??

Spark系列(四)第一部分:RDD-DataSet-DataFrame你究竟该用哪个?应该如何使用API??

Spark系列(五)Spark-GraphX的基本介绍与算子的简单使用—网络红人排名实例分解

Spark系列(六)Spark-GraphX的PageRank算法----热度排名的实例代码+图解展示

Spark系列(七)SparkGraphX下的Pregel方法----完美解决单源最短路径的应用算法

Spark系列(八)SparkSQL和集成数据源-及简单优化方案----简化工作的利器!!

Spark系列(九) Spark数据倾斜之六大使用场景—真正详细得数据倾斜实战套路!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值