这是我参与更文挑战的第15天,活动详情查看:更文挑战
解决方案六:使用随机key实现双重聚合
- 当使用了类似于groupByKey、reduceByKey这样的算子时,可以考虑使用随机key实现双重聚合,如图所示:
-
首先,通过map算子给每个数据的key添加随机数前缀,对key进行打散,将原先一样的key变成不一样的key,然后进行第一次聚合,这样就可以让原本被一个task处理的数据分散到多个task上去做局部聚合;随后,去除掉每个key的前缀,再次进行聚合。
-
此方法对于由groupByKey、reduceByKey这类算子造成的数据倾斜由比较好的效果,仅仅适用于聚合类的shuffle操作,适用范围相对较窄。如果是join类的shuffle操作,还得用其他的解决方案。
-
此方法也是前几种方案没有比较好的效果时要尝试的解决方案。
解决方案七:使用随机数扩容进行join
-
如果在进行join操作时,RDD中有大量的key导致数据倾斜,那么进行分拆key也没什么意义,此时就只能使用最后一种方案来解决问题了,对于join操作,我们可以考虑对其中一个RDD数据进行扩容,另一个RDD进行稀释后再join。
-
我们会将原先一样的key通过附加随机前缀变成不一样的key,然后就可以将这些处理后的“不同key”分散到多个task中去处理,而不是让一个task处理大量的相同key。这一种方案是针对有大量倾斜key的情况,没法将部分key拆分出来进行单独处理,需要对整个RDD进行数据扩容,对内存资源要求很高。
- 核心思想:
-
选择一个RDD,使用flatMap进行扩容,对每条数据的key添加数值前缀(1~N的数值),将一条数据映射为多条数据;(扩容)
-
选择另外一个RDD,进行map映射操作,每条数据的key都打上一个随机数作为前缀(1~N的随机数);(稀释)
-
将两个处理后的RDD,进行join操作。
-
- 局限性:
如果两个RDD都很大,那么将RDD进行N倍的扩容显然行不通;
使用扩容的方式只能缓解数据倾斜,不能彻底解决数据倾斜问题。
使用方案七对方案六进一步优化分析:
-
当RDD中有几个key导致数据倾斜时,方案六不再适用,而方案七又非常消耗资源,此时可以引入方案七的思想完善方案六:
-
对包含少数几个数据量过大的key的那个RDD,通过sample算子采样出一份样本来,然后统计一下每个key的数量,计算出来数据量最大的是哪几个key。
-
然后将这几个key对应的数据从原来的RDD中拆分出来,形成一个单独的RDD,并给每个key都打上n以内的随机数作为前缀,而不会导致倾斜的大部分key形成另外一个RDD。
-
接着将需要join的另一个RDD,也过滤出来那几个倾斜key对应的数据并形成一个单独的RDD,将每条数据膨胀成n条数据,这n条数据都按顺序附加一个0~n的前缀,不会导致倾斜的大部分key也形成另外一个RDD。
-
再将附加了随机前缀的独立RDD与另一个膨胀n倍的独立RDD进行join,此时就可以将原先相同的key打散成n份,分散到多个task中去进行join了。
-
而另外两个普通的RDD就照常join即可。
-
最后将两次join的结果使用union算子合并起来即可,就是最终的join结果。
-
近期评论