第五章_Spark核心编程_Rdd_分区器

 


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)
复制代码

 

posted @   学而不思则罔!  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界
点击右上角即可分享
微信分享提示