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的分区器

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

对RDD进行重新分区

  1. val partitioned = pairs.partitionBy(new HashPartitioner(2))
  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() 方法即可。

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

案例

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

  1. User("tom", 12), User("kobe", 12), User("mick", 22), User("jack", 23)
  1. import org.apache.spark.{Partitioner, SparkConf, SparkContext}
  2. /**
  3. * @description: TODO
  4. * @author: HaoWu
  5. * @create: 2020年08月03日
  6. */
  7. object MyPartitionerTest {
  8. def main(args: Array[String]): Unit = {
  9. val conf = new SparkConf().setAppName("RDDTest").setMaster("local[*]")
  10. val sc = new SparkContext(conf)
  11. val list = List(User("tom", 12), User("kobe", 12), User("mick", 22), User("jack", 23))
  12. val result = sc.makeRDD(list).map {
  13. case User(name, age) => (age, name)
  14. }.partitionBy(new MyPartitioner(3))
  15. result.saveAsTextFile("output")
  16. }
  17. }
  18. /**
  19. * User样例类
  20. */
  21. case class User(name: String, age: Int)
  22. /**
  23. * 自定义分区器
  24. */
  25. class MyPartitioner(num: Int) extends Partitioner {
  26. //设置分区数
  27. override def numPartitions: Int = num
  28. //分区规则
  29. override def getPartition(key: Any): Int = {
  30. //判断是否为Int类型
  31. if (!key.isInstanceOf[Int]) {
  32. 0
  33. } else {
  34. //Hash分区具有聚类的作用,相同age的会被分如同一个区
  35. key.asInstanceOf[Int] % numPartitions
  36. }
  37. }
  38. }

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. configure: error: invalid variable name: `'

    今天在交叉编译一个编解码库的时候,出现一个莫名其妙的报错,一直找不到原因,后来无意中删除了一个空格,才发现就是这个空格造成的错误. ./configure --host=arm-linux LDFLA ...

  2. 连续子序列的最大和 牛客网 剑指Offer

    连续子序列的最大和 牛客网 剑指Offer 题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量 ...

  3. 两个栈实现队列 牛客网 程序员面试金典 C++ Python

    两个栈实现队列 牛客网 程序员面试金典 C++ Python 题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. C++ //run:5ms memeory ...

  4. dart系列之:dart语言中的变量

    目录 简介 dart中的变量 定义变量 变量的默认值 Late变量 常量 总结 简介 flutter是google在2015年dart开发者峰会上推出的一种开源的移动UI构建框架,使用flutter可 ...

  5. 【接口】SpringBoot+接口开发(一)

    一.接口的简单介绍 1.什么是接口:接口及服务: 2.接口的分类:(1)系统的内部接口;(2)第三方的外部接口; 3.简述接口原理图: 4.接口协议:是指客户端跟服务器之间或者接口与接口间进行的通讯时 ...

  6. fiddler 手机+浏览器 抓包

    用fiddler对手机上的程序进行抓包   前提: 1.必须确保安装fiddler的电脑和手机在同一个wifi环境下 备注:如果电脑用的是台式机,可以安装一个随身wifi,来确保台式机和手机在同一wi ...

  7. Java学到什么程度能找到一份还不错的工作

    我的读者里有很多 Java 新人,新人是指正在学 Java 的.以及工作时间不长的年轻人,他们经常问我一个问题: Java 学到什么程度才能找到一份还不错的工作? 今天我就从我自己面试新人的角度来回答 ...

  8. Visual Studio 2019连接MySQL数据库详细教程

    前言 如果要在 Visual Studio 2019中使用MySQL数据库,首先需要下载MySQL的驱动 Visual Studio默认只显示微软自己的SQL Server数据源,点击其它也是微软自己 ...

  9. mysql 存储ipv6

    自定义列 https://groups.google.com/g/sqlalchemy/c/lZw0GipVYFw https://docs.sqlalchemy.org/en/14/core/cus ...

  10. Python 爬取 书籍

    ... import requests from bs4 import BeautifulSoup def gethtml(url,h): r = requests.get(url,headers=h ...