1. 什么是Rdd的分区器?
* key-value类型的Rdd在Shuffle时,会根据key的特质进行分区
* 分区器就是 Partitioner的一个实现类
* 通过指定 numPartitions 确定分区个数
* getPartition(key: Any) 确定分区规则
2. Spark 分区器的种类?
* HashPartitioner(默认分区器)
* 分区规则 : hash(key) % numPartitions
* 缺点 : 当 大量key相同时,会导致分区不均,导致数据倾斜
*
* RangePartitioner
* 没研究明白,待补充
*
* 自定义分区器
* 实现 Partitioner接口,自定义
3. note
* 1.Key-Value类型RDD才有分区器,非Key-Value类型RDD的分区值是None
* 2.每个RDD的分区编号范围为0~numPartitions-1,其决定数据所在分区
4. Spark分区器和MapReduce分区器的区别(自定义分区器)?
* MapReduce :
* def getPartition(key: Nothing, value: Nothing, numPartitions: Int): Int
* 可以根据 key,value 进行分区
* Spark :
* def getPartition(key: Any): Int
* 只能根据 key 进行分区
5. 代码示例
//自定义分区器
//必须是 org.apache.spark.Partitioner的实现类
//需求 : 将key按进入分区器的序号分区(将key打散)
class custPartitioner(partitions: Int) extends Partitioner {
override def numPartitions: Int = partitions
var index = 0
override def getPartition(key: Any): Int = {
index += 1
index % numPartitions
}
}
/*HashPartitioner*/
object HashPartitionerTest extends App {
val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest")
val sc: SparkContext = new SparkContext(sparkconf)
val rdd: RDD[(Int, String)] = sc.makeRDD(List((1, "x"), (1, "x"), (1, "x"), (1, "x"), (1, "x"), (2, "x"), (2, "x")), 2)
//使用 HashPartitioner 分区器
//@partitions 指定分区个数
val rdd1: RDD[(Int, String)] = rdd.partitionBy(new HashPartitioner(3))
//使用 RangePartitioner 分区器
val rdd2: RDD[(Int, String)] = rdd.partitionBy(new RangePartitioner(3, rdd))
//使用 自定义分区器
val rdd3: RDD[(Int, String)] = rdd.partitionBy(new custPartitioner(3))
// 使用 自定义分区器
// 使用匿名内部类
// 根据 key的奇偶性分区
private val rdd4: RDD[(Int, String)] = rdd.partitionBy(
new Partitioner {
override def numPartitions: Int = 3 //指定分区个数
override def getPartition(key: Any): Int = {
if (key.asInstanceOf[Int].abs % 2 == 0) {
0
} else {
1
}
}
}
)
//rdd1.saveAsTextFile("Spark_319/src/output/01")
//rdd2.saveAsTextFile("Spark_319/src/output/02")
rdd3.saveAsTextFile("Spark_319/src/output/03")
sc.stop()
}
-- HashPartitioner
part-00000
part-00001
(1,x)
(1,x)
(1,x)
(1,x)
(1,x)
part-00002
(2,x)
(2,x)
-- custPartitioner
part-00000
(1,x)
(2,x)
part-00001
(1,x)
(1,x)
(2,x)
part-00002
(1,x)
(1,x)