Spark学习之路 (十七)Spark分区

讨论QQ:1586558083

目录

正文

回到顶部

一、分区的概念

  分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务的个数,也是由RDD(准确来说是作业最后一个RDD)的分区数决定。

回到顶部

二、为什么要进行分区

  数据分区,在分布式集群里,网络通信的代价很大,减少网络传输可以极大提升性能。mapreduce框架的性能开支主要在io和网络传输,io因为要大量读写文件,它是不可避免的,但是网络传输是可以避免的,把大文件压缩变小文件,   从而减少网络传输,但是增加了cpu的计算负载。

  Spark里面io也是不可避免的,但是网络传输spark里面进行了优化:

  Spark把rdd进行分区(分片),放在集群上并行计算。同一个rdd分片100个,10个节点,平均一个节点10个分区,当进行sum型的计算的时候,先进行每个分区的sum,然后把sum值shuffle传输到主程序进行全局sum,所以进行sum型计算对网络传输非常小。但对于进行join型的计算的时候,需要把数据本身进行shuffle,网络开销很大。

spark是如何优化这个问题的呢?

  Spark把key-value rdd通过key的hashcode进行分区,而且保证相同的key存储在同一个节点上,这样对改rdd进行key聚合时,就不需要shuffle过程,我们进行mapreduce计算的时候为什么要进行shuffle?,就是说mapreduce里面网络传输主要在shuffle阶段,shuffle的根本原因是相同的key存在不同的节点上,按key进行聚合的时候不得不进行shuffle。shuffle是非常影响网络的,它要把所有的数据混在一起走网络,然后它才能把相同的key走到一起。进行shuffle是存储决定的。

  Spark从这个教训中得到启发,spark会把key进行分区,也就是key的hashcode进行分区,相同的key,hashcode肯定是一样的,所以它进行分区的时候100t的数据分成10分,每部分10个t,它能确保相同的key肯定在一个分区里面,而且它能保证存储的时候相同的key能够存在同一个节点上。比如一个rdd分成了100份,集群有10个节点,所以每个节点存10份,每一分称为每个分区,spark能保证相同的key存在同一个节点上,实际上相同的key存在同一个分区。

  key的分布不均决定了有的分区大有的分区小。没法分区保证完全相等,但它会保证在一个接近的范围。所以mapreduce里面做的某些工作里边,spark就不需要shuffle了,spark解决网络传输这块的根本原理就是这个。

  进行join的时候是两个表,不可能把两个表都分区好,通常情况下是把用的频繁的大表事先进行分区,小表进行关联它的时候小表进行shuffle过程。

  大表不需要shuffle。  

  需要在工作节点间进行数据混洗的转换极大地受益于分区。这样的转换是  cogroup,groupWith,join,leftOuterJoin,rightOuterJoin,groupByKey,reduceByKey,combineByKey 和lookup。

  分区是可配置的,只要RDD是基于键值对的即可

回到顶部

三、Spark分区原则及方法

RDD分区的一个分区原则:尽可能是得分区的个数等于集群核心数目

无论是本地模式、Standalone模式、YARN模式或Mesos模式,我们都可以通过spark.default.parallelism来配置其默认分区个数,若没有设置该值,则根据不同的集群环境确定该值

3.1 本地模式

(1)默认方式

以下这种默认方式就一个分区

结果

(2)手动设置

设置了几个分区就是几个分区

结果

(3)跟local[n] 有关

n等于几默认就是几个分区

如果n=* 那么分区个数就等于cpu core的个数

结果

本机电脑查看cpu core,我的电脑--》右键管理--》设备管理器--》处理器

(4)参数控制

结果

3.2 YARN模式

进入defaultParallelism方法

继续进入defaultParallelism方法

这个一个trait,其实现类是(Ctrl+h)

进入TaskSchedulerImpl类找到defaultParallelism方法

继续进入defaultParallelism方法,又是一个trait,看其实现类

Ctrl+h看SchedulerBackend类的实现类

进入CoarseGrainedSchedulerBackend找到defaultParallelism

totalCoreCount.get()是所有executor使用的core总数,和2比较去较大值

如果正常的情况下,那你设置了多少就是多少

回到顶部

四、分区器

(1)如果是从HDFS里面读取出来的数据,不需要分区器。因为HDFS本来就分好区了。

    分区数我们是可以控制的,但是没必要有分区器。

(2)非key-value RDD分区,没必要设置分区器

al testRDD = sc.textFile("C:\\Users\\Administrator\\IdeaProjects\\myspark\\src\\main\\hello.txt")
  .flatMap(line => line.split(","))
  .map(word => (word, 1)).partitionBy(new HashPartitioner(2))
  没必要设置,但是非要设置也行。

(3)Key-value形式的时候,我们就有必要了。

HashPartitioner

val resultRDD = testRDD.reduceByKey(new HashPartitioner(2),(x:Int,y:Int) => x+ y)
//如果不设置默认也是HashPartitoiner,分区数跟spark.default.parallelism一样
println(resultRDD.partitioner)
println("resultRDD"+resultRDD.getNumPartitions)

RangePartitioner

val resultRDD = testRDD.reduceByKey((x:Int,y:Int) => x+ y)
val newresultRDD=resultRDD.partitionBy(new RangePartitioner[String,Int](3,resultRDD))
println(newresultRDD.partitioner)
println("newresultRDD"+newresultRDD.getNumPartitions)
注:按照范围进行分区的,如果是字符串,那么就按字典顺序的范围划分。如果是数字,就按数据自的范围划分

自定义分区

需要实现2个方法

class MyPartitoiner(val numParts:Int) extends  Partitioner{
  override def numPartitions: Int = numParts
  override def getPartition(key: Any): Int = {
    val domain = new URL(key.toString).getHost
    val code = (domain.hashCode % numParts)
    if (code < 0) {
      code + numParts
    } else {
      code
    }
  }
}

object DomainNamePartitioner {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("word count").setMaster("local")

    val sc = new SparkContext(conf)

    val urlRDD = sc.makeRDD(Seq(("http://baidu.com/test", 2),
      ("http://baidu.com/index", 2), ("http://ali.com", 3), ("http://baidu.com/tmmmm", 4),
      ("http://baidu.com/test", 4)))
    //Array[Array[(String, Int)]]
    // = Array(Array(),
    // Array((http://baidu.com/index,2), (http://baidu.com/tmmmm,4),
    // (http://baidu.com/test,4), (http://baidu.com/test,2), (http://ali.com,3)))
    val hashPartitionedRDD = urlRDD.partitionBy(new HashPartitioner(2))
    hashPartitionedRDD.glom().collect()

    //使用spark-shell --jar的方式将这个partitioner所在的jar包引进去,然后测试下面的代码
    // spark-shell --master spark://master:7077 --jars spark-rdd-1.0-SNAPSHOT.jar
    val partitionedRDD = urlRDD.partitionBy(new MyPartitoiner(2))
    val array = partitionedRDD.glom().collect()

  }
}

原文地址:https://www.cnblogs.com/liuys635/p/11002781.html

时间: 2024-10-18 00:32:07

Spark学习之路 (十七)Spark分区的相关文章

Spark学习之路 (二十三)SparkStreaming的官方文档

一.SparkCore.SparkSQL和SparkStreaming的类似之处 二.SparkStreaming的运行流程 2.1 图解说明 2.2 文字解说 1.我们在集群中的其中一台机器上提交我们的Application Jar,然后就会产生一个Application,开启一个Driver,然后初始化SparkStreaming的程序入口StreamingContext: 2.Master会为这个Application的运行分配资源,在集群中的一台或者多台Worker上面开启Excuter

Spark学习之路 (八)SparkCore的调优之开发调优

讨论QQ:1586558083 目录 调优概述 原则一:避免创建重复的RDD 一个简单的例子 原则二:尽可能复用同一个RDD 一个简单的例子 原则三:对多次使用的RDD进行持久化 对多次使用的RDD进行持久化的代码示例 Spark的持久化级别 如何选择一种最合适的持久化策略 原则四:尽量避免使用shuffle类算子 Broadcast与map进行join代码示例 原则五:使用map-side预聚合的shuffle操作 原则六:使用高性能的算子 使用reduceByKey/aggregateByK

Spark学习之路 (八)SparkCore的调优之开发调优[转]

前言 在大数据计算领域,Spark已经成为了越来越流行.越来越受欢迎的计算平台之一.Spark的功能涵盖了大数据领域的离线批处理.SQL类处理.流式/实时计算.机器学习.图计算等各种不同类型的计算操作,应用范围与前景非常广泛.在美团?大众点评,已经有很多同学在各种项目中尝试使用Spark.大多数同学(包括笔者在内),最初开始尝试使用Spark的原因很简单,主要就是为了让大数据计算作业的执行速度更快.性能更高. 然而,通过Spark开发出高性能的大数据计算作业,并不是那么简单的.如果没有对Spar

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

RDD的概述 什么是RDD? RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合.RDD具有数据流模型的特点:自动容错.位置感知性调度和可伸缩性.RDD允许用户在执行多个查询时显式地将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度. RDD的属性 (1)一组分片(Partition),即数据集的基本组成单位.对于RDD来说,每个分片都会被一个计算任务处

Spark学习之路 (二十三)SparkStreaming的官方文档[转]

SparkCore.SparkSQL和SparkStreaming的类似之处 SparkStreaming的运行流程 1.我们在集群中的其中一台机器上提交我们的Application Jar,然后就会产生一个Application,开启一个Driver,然后初始化SparkStreaming的程序入口StreamingContext: 2.Master会为这个Application的运行分配资源,在集群中的一台或者多台Worker上面开启Excuter,executer会向Driver注册: 3

Spark学习之路---Spark核心概念

Spark核心概念简介 一个Spark应用都由驱动器程序发起集群上的各种并发操作,一个驱动器程序一般包含多个执行器节点,驱动器程序通过一个SaprkContext对象访问saprk.RDD(弹性分布式数据集)----分布式的元素集合,RDD支持两种操作:转化操作.行动操作,如map.reduce函数.

Spark学习之路 (七)Spark 运行流程

讨论QQ:1586558083 目录 一.Spark中的基本概念 二.Spark的运行流程 2.1 Spark的基本运行流程 三.Spark在不同集群中的运行架构 3.1 Spark on Standalone运行过程 3.2 Spark on YARN运行过程 正文 回到顶部 一.Spark中的基本概念 (1)Application:表示你的应用程序 (2)Driver:表示main()函数,创建SparkContext.由SparkContext负责与ClusterManager通信,进行资

Spark学习之路 (五)Spark伪分布式安装

讨论QQ:1586558083 目录 一.JDK的安装 1.1 上传安装包并解压 1.2 配置环境变量 1.3 验证Java版本 二.配置配置ssh localhost 2.1 检测 2.2 生成私钥和公钥秘钥对 2.3 将公钥添加到authorized_keys 2.4 赋予authorized_keys文件600的权限 2.5 修改Linux映射文件(root用户) 2.6 验证 三.安装Hadoop-2.7.5 3.1 上传解压缩 3.2 创建安装包对应的软连接 3.3 修改配置文件 3.

Spark学习之路 (二)Spark2.3 HA集群的分布式安装[转]

下载Spark安装包 从官网下载 http://spark.apache.org/downloads.html 从微软的镜像站下载 http://mirrors.hust.edu.cn/apache/ 从清华的镜像站下载 https://mirrors.tuna.tsinghua.edu.cn/apache/ 安装基础 Java8安装成功 zookeeper安装成功 hadoop2.7.5 HA安装成功 Scala安装成功(不安装进程也可以启动) Spark安装过程 上传并解压缩 [[email

Spark学习之路 (七)Spark 运行流程[转]

Spark中的基本概念 (1)Application:表示你的应用程序 (2)Driver:表示main()函数,创建SparkContext.由SparkContext负责与ClusterManager通信,进行资源的申请,任务的分配和监控等.程序执行完毕后关闭SparkContext (3)Executor:某个Application运行在Worker节点上的一个进程,该进程负责运行某些task,并且负责将数据存在内存或者磁盘上.在Spark on Yarn模式下,其进程名称为 Coarse