在spark中,框架默认使用的事hashPartitioner分区器进行对rdd分区,但是实际生产中,往往使用spark自带的分区器会产生数据倾斜等原因,这个时候就需要我们自定义分区,按照我们指定的字段进行分区。具体的流程步骤如下:

1、创建一个自定义的分区类,并继承Partitioner,注意这个partitioner是spark的partitioner

2、重写partitioner中的方法

  override def numPartitions: Int = ???
override def getPartition(key: Any): Int = ??? 代码实现:
测试数据集:
cookieid,createtime,pv
cookie1,2015-04-10,1
cookie1,2015-04-11,5
cookie1,2015-04-12,7
cookie1,2015-04-13,3
cookie1,2015-04-14,2
cookie1,2015-04-15,4
cookie1,2015-04-16,4
cookie2,2015-04-10,2
cookie2,2015-04-11,3
cookie2,2015-04-12,5
cookie2,2015-04-13,6
cookie2,2015-04-14,3
cookie2,2015-04-15,9
cookie2,2015-04-16,7

  指定按照第一个字段进行分区

步骤1:
package _core.sourceCodeLearning.partitioner

import org.apache.spark.Partitioner
import scala.collection.mutable.HashMap /**
* Author Mr. Guo
* Create 2019/6/23 - 12:19
*/
class UDFPartitioner(args: Array[String]) extends Partitioner { private val partitionMap: HashMap[String, Int] = new HashMap[String, Int]()
var parId = 0
for (arg <- args) {
if (!partitionMap.contains(arg)) {
partitionMap(arg) = parId
parId += 1
}
} override def numPartitions: Int = partitionMap.valuesIterator.length override def getPartition(key: Any): Int = {
val keys: String = key.asInstanceOf[String]
val sub = keys
partitionMap(sub)
}
}

  步骤2:

主类测试:

package _core.sourceCodeLearning.partitioner

import org.apache.spark.{SparkConf, TaskContext}
import org.apache.spark.sql.SparkSession /**
* Author Mr. Guo
* Create 2019/6/23 - 12:21
*/
object UDFPartitionerMain {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[2]").setAppName(this.getClass.getSimpleName)
val ssc = SparkSession
.builder()
.config(conf)
.getOrCreate()
val sc = ssc.sparkContext
sc.setLogLevel("WARN") val rdd = ssc.sparkContext.textFile("file:///E:\\TestFile\\analyfuncdata.txt")
val transform = rdd.filter(_.split(",").length == 3).map(x => {
val arr = x.split(",")
(arr(0), (arr(1), arr(2)))
})
val keys: Array[String] = transform.map(_._1).collect()
val partiion = transform.partitionBy(new UDFPartitioner(keys))
partiion.foreachPartition(iter => {
println(s"**********分区号:${TaskContext.getPartitionId()}***************")
iter.foreach(r => {
println(s"分区:${TaskContext.getPartitionId()}###" + r._1 + "\t" + r._2 + "::" + r._2._1)
})
})
ssc.stop()
}
}

  运行结果:

这样就是按照第一个字段进行了分区,当然在分区器的中,对于key是可以根据自己的需求随意的处理,比如添加随机数等等

spark自定义分区器实现的更多相关文章

  1. Spark自定义分区(Partitioner)

    我们都知道Spark内部提供了HashPartitioner和RangePartitioner两种分区策略,这两种分区策略在很多情况下都适合我们的场景.但是有些情况下,Spark内部不能符合咱们的需求 ...

  2. MapReduce之自定义分区器Partitioner

    @ 目录 问题引出 默认Partitioner分区 自定义Partitioner步骤 Partition分区案例实操 分区总结 问题引出 要求将统计结果按照条件输出到不同文件中(分区). 比如:将统计 ...

  3. kafka 自定义分区器

    package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.Partitioner; import org.a ...

  4. Spark源码分析之分区器的作用

    最近因为手抖,在Spark中给自己挖了一个数据倾斜的坑.为了解决这个问题,顺便研究了下Spark分区器的原理,趁着周末加班总结一下~ 先说说数据倾斜 数据倾斜是指Spark中的RDD在计算的时候,每个 ...

  5. RDD(六)——分区器

    RDD的分区器 Spark目前支持Hash分区和Range分区,用户也可以自定义分区,Hash分区为当前的默认分区,Spark中分区器直接决定了RDD中分区的个数.RDD中每条数据经过Shuffle过 ...

  6. 聊聊Spark的分区、并行度 —— 前奏篇

    通过之前的文章[Spark RDD详解],大家应该了解到Spark会通过DAG将一个Spark job中用到的所有RDD划分为不同的stage,每个stage内部都会有很多子任务处理数据,而每个sta ...

  7. 玩转Kafka的生产者——分区器与多线程

    上篇文章学习kafka的基本安装和基础概念,本文主要是学习kafka的常用API.其中包括生产者和消费者, 多线程生产者,多线程消费者,自定义分区等,当然还包括一些避坑指南. 首发于个人网站:链接地址 ...

  8. kafka producer partitions分区器(七)

    消息在经过拦截器.序列化后,就需要确定它发往哪个分区,如果在ProducerRecord中指定了partition字段,那么就不再需要partitioner分区器进行分区了,如果没有指定,那么会根据k ...

  9. Kafka的接口回调 +自定义分区、拦截器

    一.接口回调+自定义分区 1.接口回调:在使用消费者的send方法时添加Callback回调 producer.send(new ProducerRecord<String, String> ...

随机推荐

  1. hbase GC优化

    编辑配置文件 编辑 hbase-env.sh   export HBASE_OPTS="$HBASE_OPTS -XX:+UseCompressedOops -XX:+UseParNewGC ...

  2. springmvc基于注解的权限控制

    一.权限码 /** * @Title: AuthCode.java * @Package cn.com.kamfu.auth * @Description: TODO(用一句话描述该文件做什么) * ...

  3. Gym 101981K bfs

    思路:暴力让所有的骆驼和第一只骆驼合并,比如现在是第k只骆驼和第一只合并,广搜找出第k只骆驼如果想和第一只骆驼合并需要走哪一步,然后走一步,并更新所有骆驼的位置. 代码: #include <b ...

  4. P4151 [WC2011]最大XOR和路径 线性基

    题目传送门 题意:给出一幅无向图,求1到n的所有路径中最大异或和,一条边可以被重复经过. 思路: 参考了大佬的博客 #pragma GCC optimize (2) #pragma G++ optim ...

  5. rabbitMQ 问题

    1.有时候在学习或者测试的时候,发现我在一个EXCHANGE  上面绑定了多个通道,这些通道的ROUTING_KEY 各不相同.但是从发送端 发到EXCHANGE 时,却在别的通道上面也收到了该消息, ...

  6. C++中的delete加深认识

    delete操作: 我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身. 1.假如你不去释放,那么该区域的内存始终不能被其他数据所使用.2.指向该内存的指针是个局部变 ...

  7. 【leetcode】955. Delete Columns to Make Sorted II

    题目如下: We are given an array A of N lowercase letter strings, all of the same length. Now, we may cho ...

  8. Centos剔除在线用户

    CentOS踢除已登录用户的方法: 1.>先按下w查看用户终端号 2.>执行pkill -kill -t pts/1 (pts/1为w指令看到的用户终端号)命令

  9. 【LeetCode 10】正则表达式匹配

    题目链接 [题解] 看到这个题解 写的代码. 就是加个备忘录法.优化一下暴力的做法. 匹配的时候如果遇到号的话,就两种可能.不再考虑它前面一个字符了. 跳过这个或者.或者继续用前面那个字符匹配. 即d ...

  10. HBase与Hive交互操作案例

    HBase与Hive交互操作 1.环境准备 因为我们后续可能会在操作Hive的同时对HBase也会产生影响,所以Hive需要持有操作HBase的Jar,那么接下来拷贝Hive所依赖的Jar包(或者使用 ...