你必须区分两个不同的问题:
数据偏斜
如果数据分布高度偏斜(让我们假设只有一个唯一键的最坏情况),那么根据定义,输出将偏斜,更改分区器无济于事。
有一些技术可以用来部分解决问题,但整体分区并不是这里的核心问题。
分区偏差
即使数据是均匀分布的,选择不当的分区函数也会导致数据分布偏斜。例如:
val rdd = sc.parallelize(Seq((5, None), (10, None), (15, None), (20, None)), 5)
rdd
.partitionBy(new org.apache.spark.HashPartitioner(5))
.glom.map(_.size).collect
Array[Int] = Array(4, 0, 0, 0, 0)
正如您所看到的,尽管密钥分布没有倾斜,但倾斜是由 hashCode 的数据规律和不良属性引起的。
如果这样选择不同的Partitioner:
rdd
.partitionBy(new org.apache.spark.RangePartitioner(5, rdd))
.glom.map(_.size).collect
Array[Int] = Array(1, 1, 1, 1, 0)
或调整现有的属性:
rdd
.partitionBy(new org.apache.spark.HashPartitioner(7))
.glom.map(_.size).collect
Array[Int] = Array(0, 1, 0, 1, 0, 1, 1)
可以解决问题。