一文读懂spark数据倾斜

spark中出现数据倾斜的原因?

前面分析过shuffle 的原理,主要就是按照key来进行values的数据的输出,拉取和聚合的。同一个key的value,肯定会分配到同一个reduce task进行处理的。为什么会出现数据倾斜呢,举个例子,假如多个key对应的values,一共是100万,但是可能某个key对应的value数量就已经到达了98万,占了绝大多数,另外两个key,可能各分配到了一万数据。可能两个一万数据的key对应的task两分钟就执行完了。而98万条数据对应的key就大概需要 2*98 分钟才能执行完,这就是数据倾斜。

数据倾斜的表现?

a: 大部分task很快的执行完,剩下一两个执行的特别慢
b: 执行到个别task到时候,直接内存溢出,程序崩掉

如何定位数据倾斜出现的位置?

a:去程序里面找用到shuffle算子的地方,groupBykey,countByKey,reduceByKey,join等等,根据业务场景分析算子上下游数据。
b:假如出现了oom,根据log中报错的代码位置去判断哪一个stage,task出问题了。

数据倾斜解决方案:

a:聚合数据源,

1.在进行shuffle之前,按照某种粒度,对key对应的value进行聚合,把多条数据聚合成一条数据,减少数据量。
2:对key放粗粒度度,增加key对数量,减少key对应的value数量

b:提高shuffle操作reduce的并行度

在调用shuffle算子函数的时候,传入一个并行度数量的参数,这样可以让每个reduce task分配到更少的数据。但是这样治标不治本,没有从根本上改变数据倾斜的本质和问题。

c:随机key实现双重聚合

在使用groupByKey和reduceByKey的时候适合该方式,原理是先对key值前面加上随机数,然后进行reuceByKey,然后map去掉前缀,然后再执行reduceByKey操作,这种方式对数据倾斜有着比较好的效果。

d:将reduce join 转换为 map join

该种方式适合大表和小表的情况,因为要把小表搞成广播变量,在每个进程中都会存储一份,所以不宜过大。然后拿大表直接map该广播变量执行操作即可。

e:sample 采样倾斜key进行两次join

原理是如果某个key对应的数据特别多,可以单独将该key对应的数据拉出来,进行单独的join操作,最后将join后的表进行union操作.该种方式也可以进一步优化,可以对单独拉出来的key前缀打上随机数,这样性能会更好一些。

f:使用随机数以及扩容表进行join

该种方式是对数据倾斜的缓解,
1, 选择一个RDD要用 flatMap,进行扩容(比较小的 RDD),将每条数据,映射为多条数据,每个映射出来的数据,都带了一个 n 以内的随机数,通常来说,会选择 10 以内。
2, 将另外一个 RDD,做普通的 map 映射操作,每条数据都打上一个 10 以内的随机数。
3, 最后,将两个处理后的 RDD,进行 join 操作。

你可能感兴趣的:(大数据开发,java)