Spark(九)【RDD的分区和自定义Partitioner】
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】的更多相关文章
- Spark RDD概念学习系列之Pair RDD的分区控制
不多说,直接上干货! Pair RDD的分区控制 Pair RDD的分区控制 (1) Spark 中所有的键值对RDD 都可以进行分区控制---自定义分区 (2)自定义分区的好处: 1) 避免数据倾 ...
- RDD的分区相关
分区是rdd的一个属性,每个分区是一个迭代器 分区器是决定数据数据如何分区 RDD划分成许多分区分布到集群的节点上,分区的多少涉及对这个RDD进行并行计算的粒度.用户可以获取分区数和设置分区数目,默认 ...
- Spark之 RDD
简介 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合. Resilien ...
- Spark之RDD的定义及五大特性
RDD是分布式内存的一个抽象概念,是一种高度受限的共享内存模型,即RDD是只读的记录分区的集合,能横跨集群所有节点并行计算,是一种基于工作集的应用抽象. RDD底层存储原理:其数据分布存储于多台机器上 ...
- Spark之RDD弹性特性
RDD作为弹性分布式数据集,它的弹性具体体现在以下七个方面. 1.自动进行内存和磁盘数据存储的切换 Spark会优先把数据放到内存中,如果内存实在放不下,会放到磁盘里面,不但能计算内存放下的数据,也能 ...
- RDD(六)——分区器
RDD的分区器 Spark目前支持Hash分区和Range分区,用户也可以自定义分区,Hash分区为当前的默认分区,Spark中分区器直接决定了RDD中分区的个数.RDD中每条数据经过Shuffle过 ...
- 关于Spark中RDD的设计的一些分析
RDD, Resilient Distributed Dataset,弹性分布式数据集, 是Spark的核心概念. 对于RDD的原理性的知识,可以参阅Resilient Distributed Dat ...
- Spark核心RDD、什么是RDD、RDD的属性、创建RDD、RDD的依赖以及缓存、
1:什么是Spark的RDD??? RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行 ...
- [转]Spark学习之路 (三)Spark之RDD
Spark学习之路 (三)Spark之RDD https://www.cnblogs.com/qingyunzong/p/8899715.html 目录 一.RDD的概述 1.1 什么是RDD? ...
随机推荐
- 转:VCS仿真vivado IP的方法
vivado中的仿真库和模型与ISE中的是不一样的,因此在vivado中使用VCS进行仿真的方法也与ISE中不一样. VCS可以通过两种方法对XILINX的器件进行功能仿真和门级仿真,这两种方法是 P ...
- mdev 响应热插拔事件
热插拔事件是从内核空间发送到用户空间的通知,一般这时候系统配置出现了变化,比如插入/移除耳机,插入/移除SD卡或者USB存储设备等. 热插拔事件默认会调用/sbin/hotplug来加载驱动程序,创建 ...
- 手把手教你学Dapr - 5. 状态管理
上一篇:手把手教你学Dapr - 4. 服务调用 介绍 使用状态管理,您的应用程序可以将数据作为键/值对存储在支持的状态存储中. 您的应用程序可以使用 Dapr 的状态管理 API 使用状态存储组件来 ...
- MySQL基础语句(查询)
students表 id class_id name gender score 1 1 小明 M 90 2 1 小红 F 95 3 1 小军 M 88 4 1 小米 F 73 5 2 小白 F 81 ...
- [loj2478]林克卡特树
原题等价于选择恰好$k+1$条不相交(无公共点)的路径使得边权和最大 证明:对于原题中的最优解,一定包含了k条0边权的边(否则可以将未使用的边删掉,然后将这条路径的末尾与不在同一个连通块内的点连边), ...
- shell常用集锦
该文整理一些常用的shell用法,及语法,并非介绍如何使用 变量 变量可分为两类:环境变量ENV(全局)和局部变量. bash环境变量 变量名 含义 _= 上一条命令的最后一个参数 BASH_VERS ...
- es使用postmain进行数据的增删改查
es的基本安装 安装遇到的问题 java本地环境和es环境冲突 https://www.cnblogs.com/q1359720840/p/14077049.html ,看要使用jdk1 ...
- git不显示提交代码
今天提交代码找不到提交的具体代码,找了好半天,最后发现是右边能下拉能拉下去,尴尬.
- Python迭代器生成器与生成式
Python迭代器生成器与生成式 什么是迭代 迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果.每一次对过程的重复称为一次"迭代",而每一次迭代得到的结果会作为下一次迭 ...
- 【Cloud Computing】Hadoop环境安装、基本命令及MapReduce字数统计程序
[Cloud Computing]Hadoop环境安装.基本命令及MapReduce字数统计程序 1.虚拟机准备 1.1 模板机器配置 1.1.1 主机配置 IP地址:在学校校园网Wifi下连接下 V ...