spark的自定义partitioner

在hadoop的mapreduce中默认patitioner是HashPartitioner,我们可以自定义Partitioner可以有效防止数据倾斜, 在Spark里面也是一样,在Spark里也是默认的HashPartitioner, 如果自己想自己定义Partitioner继承org.apache.spark里面的Partitioner并且重写它里面的两个方法就行了.

  • 模板如下:
//只需要继承Partitioner,重写两个方法
class MyPartitioner(val num: Int) extends Partitioner {

  //这里定义partitioner个数
  override def numPartitions: Int = ???

  //这里定义分区规则
  override def getPartition(key: Any): Int = ???
}
  • 具体案例:

对List里面的单词进行wordcount,并且输出按照每个单词的长度分区输出到不同文件里面

自定义partitioner如下:

class MyPartitioner(val num: Int) extends Partitioner {
  override def numPartitions: Int = num

  override def getPartition(key: Any): Int = {
    val len = key.toString.length

    //根据单词长度对分区个数取模
    len % num
  }
}
  • main方法:
object xy {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("urlLocal").setMaster("local[2]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.parallelize(List("lijie hello lisi", "zhangsan wangwu mazi", "hehe haha nihaoa heihei lure hehe hello word"))

    val rdd2 = rdd1.flatMap(_.split(" ")).map(x => {
      (x, 1)
    }).reduceByKey(_ + _)

    //这里指定自定义分区,然后输出
    val rdd3 = rdd2.sortBy(_._2).partitionBy(new MyPartitioner(4)).mapPartitions(x => x).saveAsTextFile("C:\\Users\\Administrator\\Desktop\\out01")

    println(rdd2.collect().toBuffer)

    sc.stop()
  }
}
  • 结果:

因为这里定义的是4个partition 所以最后产生4个文件 如图:

spark的自定义partitioner_第1张图片

其中part-00000 和 part-00001如下:

spark的自定义partitioner_第2张图片

其中part-00002 和 part-00003如下:

spark的自定义partitioner_第3张图片

其中part-00000中zhangsan的长度对4取模为0和这个文件中其他较短的单词一样,所以在一个分区, part-00003没有内容,说明上面的单词的长度对4取模结果没有为3的

你可能感兴趣的:(spark)