spark自定义分区器实现

前言:

为什么我们要进行自定义分区
当spark进行数据处理key-value类型数据时,会遇到数据由于key值的分布不均倾斜的情况,为了使得资源的合理布置我们会进行重分区,根据spark内部提供的分区器 HashPartitioner & RangePartitioner,我们也可以实现自定义

不bb了:

test case:用如下数据做word count 实现自定义分区

hadoop,
spark
hive
hive
spark
hbase,
hbase
hbase
hbase,
hbase
kafka
kafka,

coding as below:
为了使得每一个分区都能都直接在命令行直接见到分区情况,我使用了mapPartitions 对value都进行+1 的操作,顺便也是做一下算子的练习

package com.brd.engine

import com.brd.util.sparkUtils.partitionTest
import org.apache.spark.{HashPartitioner, RangePartitioner, SparkConf, SparkContext}

object SparkTest {
  /**@desc
   * @Author brandon
   * @param args
   */

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setAppName("SparkTest")
      .setMaster("local[1]")
    val sc = new SparkContext(conf)
    sc.setLogLevel("ERROR")
    //sparkUtils.mapPartUse(sc)

    val rdd = sc.textFile("src/data/wd.txt")
    val rdd2 = rdd.flatMap(line => line.split(" ")).map(word => {
      word.replaceAll(",", "").trim
    }).map(word => (word, 1))
      .reduceByKey(_ + _)
    .repartitionAndSortWithinPartitions(new partitionTest(4))
      // 这里可以将mapPartitions的内部结构进行封装为函数传入
      .mapPartitions(this.mapUse2)
    rdd2.foreach(x => println(x))
    sc.stop()
  }

  //1. 这里做一个简单的函数赋值,来进行封装
  val mapUse:Iterator[(String,Int)]=>Iterator[(String,Int)]=x=>{
    println("**********************the partition line ***********************")
    x.toList.map(y => (y._1, y._2 + 1)).toIterator
  }
  //2.
  val mapUse2=(x:Iterator[(String,Int)])=>{
    println("**********************the partition line ***********************")
    x.toList.map(y => (y._1, y._2 + 1)).toIterator
  }
}

--------------------自定义分区器的实现---------------------------------


  /**
   * @description input a variable to confirm number of partitions
   * and extends  Partitioner and override function - numPartitions & getPartition
   *
   * @numPartitions to ensure number of partitions
   * @getPartition  according to rule to separate data into different partition
   *
   * @case analysis  : distribute key="hbase" into partition 1 
   *                   distribute key="spark" into partition 2
   *                   others into partition 0
   */

  class partitionTest(Partitions:Int) extends Partitioner {
    override def numPartitions: Int = Partitions
    override def getPartition(key: Any):Int = {
      val a =if (key.toString.indexOf("hbase")!= -1) {
        1
      }else if (key.toString.indexOf("spark")!= -1){
        2
      }else{
        0
      }
      a
    }
  }

从代码块来看是做的四个分区 来看看打印效果:

定义四个分区 hbase 和spark 都是在单独分区内

**********************the partition line ***********************
**********************the partition line ***********************
(hadoop,2)
(hive,3)
(kafka,3)
**********************the partition line ***********************
(hbase,6)
**********************the partition line ***********************
(spark,3)

定义三个分区 ,hbase 和spark同样也是在单独的分区内

**********************the partition line ***********************
(hadoop,2)
(hive,3)
(kafka,3)
**********************the partition line ***********************
(hbase,6)
**********************the partition line ***********************
(spark,3)

看来已经实现了自定义分区

End Respect.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值