Spark-core之RDD核心概念

一、Spark包括什么

spark的核心是Spark Core,其中上面的Spark Sql对接的是Hive等结构化查询,Spark Streaming是对接的流式计算,后面的那两个也是主要用在科学任务中,但是他们的基础都是spark core,而Spark core的核心就是RDD操作,RDD的操作重要的就是算子,也就是说,掌握了算子基本上就掌握了spark的基础。

二、RDD

1、是什么?

   简单的一句话就是,为用户封装了底层对数据的复杂抽象和处理,给用户提供了对数据转换,求值等操作。

RDD的全称是,Resilient Distributed Dataset,弹性分布式数据集,弹性体现在哪?本人认为,弹性最主要的是体现在RDD能够通过依赖形成DGA,DGA就确定了RDD的一系列操作的集合,就相当于一套模板,而分布式就体现在可以将数据分布在各个分区上,能提高并行度,当然这可以动态调整,那么,在每个分区上执行一系列DGA的操作,如果是每个RDD都是窄依赖,那么就不用做聚合,那么这个速度是非常快的,所以说,RDD的弹性和分布式特点很显而易见。

2、做了什么?主要通过算子实现

      

3、特性:

         不可变(只读),RDD一旦创建,内容是不可以变的,如果想修改内容就会创建一个新的RDD,其实和java中的String很像、

         可分区,RDD的数据存储在Executor中,一个Exeutor有多个分区,RDD的分区数可以根据需求动态改变,在Spark中,分区的多少就是并行度是多少。

        RDD的弹性,  表现在存储、分区、计算以及容错,  弹性指的是什么呢?其实是伸缩性和容错性的体现

         依赖,也就是,多个RDD之间可以构成先后顺序,形成DGA图,从而形成一系列操作

         缓存,因为RDD是只读的,所以如果是多个程序使用同一个RDD,则可以将RDD先缓存下来,待日后重用

         检查点,checkpoint,RDD支持checkpoint将数据保存到持久化的存储中,这样就可以切断之前的血缘关系,因为checkpoint后的RDD不需要知道它的父RDDs了,它可以从checkpoint处拿到数据。

   下面是RDD特性详解

4、特性之 弹性

   1)  存储弹性:  自动进行内存和磁盘数据存储的切换

           Spark优先把数据放到内存中,如果内存放不下,就会放到磁盘里面,程序进行自动的存储切换

    2)  容错弹性:基于血统的高效容错机制---很重要

    在RDD进行转换和动作的时候,会形成RDD的Lineage依赖链,当某一个RDD失效的时候,可以通过重新计算上游的RDD来重新生成丢失的RDD数据。

    3)数据分片的高度弹性

    可以根据业务的特征,动态调整数据分片的个数,提升整体的应用执行效率。

    RDD全称叫做弹性分布式数据集(Resilient Distributed Datasets),它是一种分布式的内存抽象表示一个只读的记录分区的集合,它只能通过其他RDD转换而创建,为此,RDD支持丰富的转换操作(如map, join, filter, groupBy等),通过这种转换操作,新的RDD则包含了如何从其他RDDs衍生所必需的信息,所以说RDDs之间是有依赖关系的。基于RDDs之间的依赖,RDDs会形成一个有向无环图DAG,该DAG描述了整个流式计算的流程,实际执行的时候,RDD是通过血缘关系(Lineage)一气呵成的,即使出现数据分区丢失,也可以通过血缘关系重建分区,总结起来,基于RDD的流式计算任务可描述为:从稳定的物理存储(如分布式文件系统)中加载记录,记录被传入由一组确定性操作构成的DAG,然后写回稳定存储。另外RDD还可以将数据集缓存到内存中,使得在多个操作之间可以重用数据集,基于这个特点可以很方便地构建迭代型应用(图计算、机器学习等)或者交互式数据分析应用。可以说Spark最初也就是实现RDD的一个分布式系统,后面通过不断发展壮大成为现在较为完善的大数据生态系统,简单来讲,Spark-RDD的关系类似于Hadoop-MapReduce关系。

    4)计算弹性

    Task如果失败会自动进行特定次数的重试  和MR很像

       RDD的计算任务如果运行失败,会自动进行任务的重新计算,默认次数是4次。

    Stage如果失败会自动进行特定次数的重试

      如果Job的某个Stage阶段计算失败,框架也会自动进行任务的重新计算,默认次数也是4次。

   Checkpoint和Persist可主动或被动触发

    RDD可以通过Persist持久化将RDD缓存到内存或者磁盘,当再次用到该RDD时直接读取就行。也可以将RDD进行检查点,检查点会将数据存储在HDFS中,该RDD的所有父RDD依赖都会被移除。

    数据调度弹性

    Spark把这个JOB执行模型抽象为通用的有向无环图DAG,可以将多Stage的任务串联或并行执行,调度引擎自动处理Stage的失败以及Task的失败。

5、特性之 分区

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

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

下面我们仅讨论Spark默认的分区个数,这里分别就parallelizetextFile具体分析其默认的分区数

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

  • 本地模式:默认为本地机器的CPU数目,若设置了local[N],则默认为N
  • Apache Mesos:默认的分区数为8
  • Standalone或YARN:默认取集群中所有核心数目的总和,或者2,取二者的较大值

结论:

  1. 对于parallelize来说,没有在方法中的指定分区数,则默认为spark.default.parallelism
  2. 对于textFile来说,没有在方法中的指定分区数,则默认为min(defaultParallelism,2),而defaultParallelism对应的就是spark.default.parallelism。如果是从hdfs上面读取文件,其分区数为文件分片数(128MB/片)
  3. 分区数就一个原则,默认尽可能的使用能用到的CPU等计算资源

     KV型自定义分区器需要继承 Partitioner 
class CustomerPar(par:Int) extends org.apache.spark.Partitioner {
   override def numPartitions:Int = par
   override def getPartition(key: Any):Int = {
      key.toString.toInt%par
   }

6、RDD特性之 依赖

 RDDs通过操作算子进行转换,转换得到的新RDD包含了从其他RDDs衍生所必需的信息,RDDs之间维护着这种血缘关系,也称之为依赖。如下图所示,依赖包括两种,一种是窄依赖,RDDs之间分区是一一对应的,另一种是宽依赖,下游RDD的每个分区与上游RDD(也称之为父RDD)的每个分区都有关,是多对多的关系。

    通过RDDs之间的这种依赖关系,一个任务流可以描述为DAG(有向无环图),如下图所示,在实际执行过程中宽依赖对应于Shuffle(图中的reduceByKey和join),窄依赖中的所有转换操作可以通过类似于管道的方式一气呵成执行(图中map和union可以一起执行)。

7、特性之  缓存

  如果在应用程序中多次使用同一个RDD,可以将该RDD缓存起来,该RDD只有在第一次计算的时候会根据血缘关系得到分区的数据,在后续其他地方用到该RDD的时候,会直接从缓存处取而不用再根据血缘关系计算,这样就加速后期的重用。如下图所示,RDD-1经过一系列的转换后得到RDD-n并保存到hdfs,RDD-1在这一过程中会有个中间结果,如果将其缓存到内存,那么在随后的RDD-1转换到RDD-m这一过程中,就不会计算其之前的RDD-0了。

8、特性之 checkpoint

虽然RDD的血缘关系天然地可以实现容错,当RDD的某个分区数据失败或丢失,可以通过血缘关系重建。但是对于长时间迭代型应用来说,随着迭代的进行,RDDs之间的血缘关系会越来越长,一旦在后续迭代过程中出错,则需要通过非常长的血缘关系去重建,势必影响性能。为此,RDD支持checkpoint将数据保存到持久化的存储中,这样就可以切断之前的血缘关系,因为checkpoint后的RDD不需要知道它的父RDDs了,它可以从checkpoint处拿到数据。

       也就说,checkpoint能够将数据进行持久化,而且最关键的,也就是和缓存最大的区别就是,checkpoint可以不用关心之前的RDD的依赖连,用到数据的时候,直接拿数据,而上面介绍的缓存,必须存在这个 依赖连,一般某个executor宕机,那之前的RDD链就找不到,同时在cache中的数据也会请清除,也就是,checkpoint具有更高的容错性。

怎么设置?

  1、通过sc设定检查点的地址, jar包内有效
      sc.setCheckpointDir("hdfs://master01:9000/checkpoint")
   2、rdd调用checkpoint      rdd.checkpoint
持久机制策略

另外解析:https://blog.csdn.net/imbetter/article/details/80023338

9、rdd的任务切分和Stage

          1、一个jar包就是一个应用程序
          2、一个行动操作就会触发一个job
          3、一个job包含多个stage,这些stage的运行通过有向无环图来运行
          4、一个stage中包含多个task,一个task处理一个分区的数据,所以分区数又叫并行度,

             spark中有两类task,一类是shuffleMapTask,一类是resultTask,详见https://blog.csdn.net/a1043498776/article/details/54889922

为什么要有stage这个概念呢? 其实这也是spark的高明之处,spark怎么才能实现MR中的map和reduce,怎么控制呢?通过使用stage

执行代码从前往后执行,划分stage是从后往前划分,从最后往前扫描代码,当遇到宽依赖时,将宽依赖前面的所有代码划分为一个stage。

总结:

1、给定一个RDD可以获得什么信息?

        1、分区数以及分区方式;2、由父RDDs衍生而来的相关依赖信息;3、计算每个分区的数据,计算步骤为:1)如果被缓存,则从缓存中取的分区的数据;2)如果被checkpoint,则从checkpoint处恢复数据;3)根据血缘关系计算分区的数据。

2、本文主要是围绕着RDD进行讲述, 主要是讲述了RDD的特性,总的来说,rdd基本特性就是弹性和分区,一个是提供了高容错性的DGA, 一个是提供了rdd的并行度,而缓存和checkpoint是从性能和安全上提升rdd,两者是相结合使用的,既有区别又要共同使用,要记住两个的区别是什么,以及持久化的策略是什么。

其次本文还简述了一个rdd的执行,其中先从spark任务中说明了任务的切分和执行的颗粒度以及顺序,当然,整个任务的执行的最小单元就是rdd,执行的结果无非就是从一个rdd变成新的rdd,然后从一个任务task变成另个task,在从一个stage转变成另一个stage,这才是一个job的结果,

当然,从stage的划分到rdd形成的DGA都离不开依赖,两种依赖的概念要理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值