数据倾斜是指少量的Task运行大量的数据,可能会导致OOM。数据过量是所有的Task都很慢。避免数据倾斜的方式主要有:
- 按照Key分组后,一组数据拼接成一个字符串,这样一个Key只有一条数据了。这个方式个人觉得有点僵硬。
- 增大或缩小Key的粒度:增大粒度一个Key包含更多的数据量。有时增大Key的粒度会降低数据倾斜,主要还是Key的数据量分布尽量均匀。
- 适当增大Shuffle阶段中Reduce任务的数量,可能会降低数据倾斜。
- 使用随机数放入Key中(放在字符串前面),Key的数量增加,但是每个Key的数据量相对均匀了。第一次聚合按照带随机数的Key,第二次对去掉随机数的真实Key进行聚合。
- 将join转为map join,可以选择一个较小RDD进行collect之后进行广播,然后在大RDD的map方法中遍历小RDD的数据,这样可以避免Shuffle,降低数据倾斜的可能性。
- 对倾斜数据进行采样后join,对导致数据倾斜的单个Key单独采样,形成单独的RDD。例如,有一个Key的数据运行较慢,可以单独对这个Key采样(采样方式可以是这个Key的全部也可以是这个Key的一部分)形成单独的RDD。然后以分开的RDD进行后面的join(这是容易导致倾斜的操作)等,最后将结果union起来即可。
- 使用随机数扩容进行join,join两边的rdd的Key前加一个1-N随机数(相同Key随机数必须不同),右边RDD每个Key增加1-N个数到该Key,扩容了N倍,然后进行join,这样保证join后的的数据量和之前是一致的。这种方式扩大了数倍的数据量,数据量大了不建议用。
- 可以使用countByKey检查哪些数据倾斜大,然后结合上面6和7情况的使用。