spark的分区

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

注意

(1)只有Key-Value类型的RDD才有分区器的,非Key-Value类型的RDD,分区器的值是None

(2)每个RDD的分区ID范围:0~numPartitions-1,决定这个值是属于那个分区的。

查看RDD的分区器

scala> val pairs = sc.parallelize(List((1,1),(2,2),(3,3)))
pairs: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[3] at
scala> pairs.partitioner
res1: Option[org.apache.spark.Partitioner] = None

对RDD进行重新分区

val partitioned = pairs.partitionBy(new HashPartitioner(2))
partitioned: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[4] at partitionBy at <console>:27

一. Hash分区

HashPartitioner分区的原理:对于给定的key,计算其hashCode,并除以分区的个数取余,如果余数小于0,则用余数+分区的个数(否则加0),最后返回的值就是这个key所属的分区ID。

聚类! key相同,hashCode相同,分配到同一个区

问题:数据倾斜,每个分区中数据量的不均匀

二. Ranger分区

​ 将一定范围内的数映射到某一个分区内,尽量保证每个分区中数据量的均匀,而且分区与分区之间是有序的,一个分区中的元素肯定都是比另一个分区内的元素小或者大,但是分区内的元素是不能保证顺序的

实现过程:

​ ①抽样产生边界数组

​ ②将元素根据边界数组判断属于哪个区

三. 自定义Partitioner

实现过程

要实现自定义的分区器,你需要继承 org.apache.spark.Partitioner 类并实现下面三个方法。

(1)numPartitions: Int:返回创建出来的分区数。

(2)getPartition(key: Any): Int:返回给定键的分区编号(0到numPartitions-1)。

使用

使用自定义的 Partitioner 是很容易的:只要把它传给 partitionBy() 方法即可。

使用自定义分区器,传给 partitionBy() 方法
scala> val par = data.partitionBy(new MyCustomerPartitioner(2))
par: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[2] at partitionBy at <console>:27
查看重新分区后的数据分布
scala> par.mapPartitionsWithIndex((index,items)=>items.map((index,_))).collect
res3: Array[(Int, (Int, Int))] = Array((0,(2,2)), (0,(4,4)), (0,(6,6)), (1,(1,1)), (1,(3,3)), (1,(5,5)))

案例

需求:有以下数据,希望年龄相同的进入同一个区。

User("tom", 12), User("kobe", 12), User("mick", 22), User("jack", 23)
import org.apache.spark.{Partitioner, SparkConf, SparkContext}

/**
* @description: TODO
* @author: HaoWu
* @create: 2020年08月03日
*/
object MyPartitionerTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("RDDTest").setMaster("local[*]")
val sc = new SparkContext(conf)
val list = List(User("tom", 12), User("kobe", 12), User("mick", 22), User("jack", 23))
val result = sc.makeRDD(list).map {
case User(name, age) => (age, name)
}.partitionBy(new MyPartitioner(3))
result.saveAsTextFile("output")
}
} /**
* User样例类
*/
case class User(name: String, age: Int) /**
* 自定义分区器
*/
class MyPartitioner(num: Int) extends Partitioner {
//设置分区数
override def numPartitions: Int = num //分区规则
override def getPartition(key: Any): Int = {
//判断是否为Int类型
if (!key.isInstanceOf[Int]) {
0
} else {
//Hash分区具有聚类的作用,相同age的会被分如同一个区
key.asInstanceOf[Int] % numPartitions
}
}
}

Spark(九)【RDD的分区和自定义Partitioner】的更多相关文章

  1. Spark RDD概念学习系列之Pair RDD的分区控制

    不多说,直接上干货! Pair RDD的分区控制 Pair RDD的分区控制 (1) Spark 中所有的键值对RDD 都可以进行分区控制---自定义分区 (2)自定义分区的好处:  1) 避免数据倾 ...

  2. RDD的分区相关

    分区是rdd的一个属性,每个分区是一个迭代器 分区器是决定数据数据如何分区 RDD划分成许多分区分布到集群的节点上,分区的多少涉及对这个RDD进行并行计算的粒度.用户可以获取分区数和设置分区数目,默认 ...

  3. Spark之 RDD

    简介 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合. Resilien ...

  4. Spark之RDD的定义及五大特性

    RDD是分布式内存的一个抽象概念,是一种高度受限的共享内存模型,即RDD是只读的记录分区的集合,能横跨集群所有节点并行计算,是一种基于工作集的应用抽象. RDD底层存储原理:其数据分布存储于多台机器上 ...

  5. Spark之RDD弹性特性

    RDD作为弹性分布式数据集,它的弹性具体体现在以下七个方面. 1.自动进行内存和磁盘数据存储的切换 Spark会优先把数据放到内存中,如果内存实在放不下,会放到磁盘里面,不但能计算内存放下的数据,也能 ...

  6. RDD(六)——分区器

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

  7. 关于Spark中RDD的设计的一些分析

    RDD, Resilient Distributed Dataset,弹性分布式数据集, 是Spark的核心概念. 对于RDD的原理性的知识,可以参阅Resilient Distributed Dat ...

  8. Spark核心RDD、什么是RDD、RDD的属性、创建RDD、RDD的依赖以及缓存、

    1:什么是Spark的RDD??? RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行 ...

  9. [转]Spark学习之路 (三)Spark之RDD

    Spark学习之路 (三)Spark之RDD   https://www.cnblogs.com/qingyunzong/p/8899715.html 目录 一.RDD的概述 1.1 什么是RDD? ...

随机推荐

  1. Latex使用CJK包添加字体

    最近写论文时有个中文期刊提供的LaTeX模板使用CJK宏包,大致是这样的: \documentclass{article} \usepackage{CJK} \begin{document} \beg ...

  2. request/response解决中文乱码!!!

    Request中文乱码问题以及解决方案 补充三个知识点: Get是URL解码方式.默认解码格式是Tomcat编码格式.所以URL解码是UTF-8,覆盖掉了request容器解码格式 Post是实体内容 ...

  3. git clone报错处理

    git clone过大的仓库时会报以下错误 remote: aborting due to possible repository corruption on the remote side. fat ...

  4. python datetime 增减以月为单位的时间段

    datetime.timedelta(days=10)  # 可以 datetime.timedelta(months=1)   # 不可以 替代: from datetime import date ...

  5. java自定义序列化

    自定义序列化 1.问题引出 在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Ser ...

  6. 🏆【Alibaba中间件技术系列】「RocketMQ技术专题」小白专区之领略一下RocketMQ基础之最!

    应一些小伙伴们的私信,希望可以介绍一下RocketMQ的基础,那么我们现在就从0开始,进入RocketMQ的基础学习及概念介绍,为学习和使用RocketMQ打好基础! RocketMQ的定位 Rock ...

  7. 浏览器 Proxy SwitchyOmega 插件设置代理访问内网服务器

    使用Proxy SwitchyOmega 插件通过代理 直接访问到内网网站 一.使用场景 如下图所示,如果在电脑的网络设置中开启代理,每次更换代理就需要进入这里设置改变代理.且我们可能回需求到两个网页 ...

  8. 【Tool】IntelliJ IDEA Ultimate2019.1 中文版 安装

    IntelliJ IDEA Ultimate2019.1 2019-07-26  09:26:24  by冲冲 1. 下载 https://mp.weixin.qq.com/s/SdFQqGzMy-g ...

  9. 查询某个信息下只有一条数据的sql

  10. 各种多项式操作的 n^2 递推

    zszz,使用 NTT 可以在 \(\mathcal O(n\log n)\) 的时间内求出两个多项式的卷积.以及一个多项式的 \(\text{inv},\ln,\exp,\text{sqrt}\) ...