Spark基础

一.基础


1. RDD机制

  1. rdd分布式弹性数据集,简单的理解成⼀种数据结构,是spark框架上的通⽤货币。 所有算⼦都是基于rdd来执⾏的,不同的场景会有不同的rdd实现类,但是都可以进⾏互相转换。 rdd执⾏过程中会形成dag图,然后形成lineage血缘关系保证容错性等。 从物理的⾓度来看rdd存储的是block和node之间的映射。

  2. RDD是spark提供的核⼼抽象,全称为弹性分布式数据集。

  3. RDD在逻辑上是⼀个hdfs⽂件,在抽象上是⼀种元素集合,包含了数据。它是被分区的,分为多个分区,每个分区分布在集群中的不同结点上,从⽽让RDD中的数据可以被并⾏操作(分布式数据集) ⽐如有个RDD有90W数据, 3个partition,则每个分区上有30W数据。 RDD通常通过Hadoop上的⽂件,即HDFS或者HIVE表来创建,还可以通过应⽤程序中的集合来创建;

  4. RDD最重要的特性就是容错性,可以⾃动从节点失败中恢复过来。即如果某个结点上的RDD partition因为节点故障,导致数据丢失,那么RDD可以通过⾃⼰的数据来源重新计算该partition。这⼀切对使⽤者都是透明的RDD的数据默认存放在内存中,但是当内存资源不⾜时, spark会⾃动将RDD数据写⼊磁盘。⽐如某结点内存只能处理20W数据,那么这20W数据就会放⼊内存中计算,剩下10W放到磁盘中。 RDD的弹性体现在于RDD上⾃动进⾏内存和磁盘之间权衡和切换的机制。


2.基础算子


2.1. map和mapPartitions区别
  1)map:每次处理一条数据

  2)mapPartitions:每次处理一个分区数据

 2.2 Repartition和Coalesce区别
  1)关系:

  两者都是用来改变RDD的partition数量的

  repartition底层调用的就是coalesce方法:coalesce(numPartitions, shuffle = true)

  2)区别:

  repartition一定会发生shuffle,coalesce根据传入的参数来判断是否发生shuffle

  一般情况下增大rdd的partition数量使用repartition,减少partition数量时使用coalesce

2.3 reduceByKey与groupByKey的区别
  reduceByKey:具有预聚合操作

  groupByKey:没有预聚合

  在不影响业务逻辑的前提下,优先采用reduceByKey。

2.4 reduceByKey、foldByKey、aggregateByKey、combineByKey区别
ReduceByKey    没有初始值    分区内和分区间逻辑相同
foldByKey    有初始值    分区内和分区间逻辑相同
aggregateByKey    有初始值    分区内和分区间逻辑可以不同
combineByKey    初始值可以变化结构    分区内和分区间逻辑不同
2.5 获取RDD分区数目两种方式
  rdd.getNumPartitions();

  rdd.partitions.length;

3. Spark任务的划分


  (1)Application:初始化一个SparkContext即生成一个Application;

  (2)Job:一个Action算子就会生成一个Job;

  (3)Stage:Stage等于宽依赖的个数加1;

  (4)Task:一个Stage阶段中,最后一个RDD的分区个数就是Task的个数。Spark中的Task有2种类型:
  ① result task类型,最后一个task;
  ② shuffleMapTask类型,除了最后一个task都是此类型;

4. RDD持久化


  spark 非常重要的一个功能特性就是可以将 RDD 持久化在内存中。调用 cache()和 persist()方法即可。

  cache后面接了其它算子之后起不到缓存应有的效果,因为会重新触发cache。

  cache()和 persist()的区别在于, cache()是 persist()的一种简化方式, cache()的底层就是调用 persist()的无参版本persist(MEMORY_ONLY), 将数据持久化到内存中。如果需要从内存中清除缓存, 可以使用 unpersist()方法。 RDD 持久化是可以手动选择不同的策略的。 在调用 persist()时传入对应的 StorageLevel 即可。

  (1)MEMORY_ONLY:以⾮序列化的Java对象的⽅式持久化在JVM内存中。如果内存⽆法完全存储RDD所有的partition,那么那些没有持久化的partition就会在下⼀次需要使⽤它的时候,被重新计算。

  (2)MEMORY_AND_DISK:同上,但是当某些partition⽆法存储在内存中时,会持久化到磁盘中。下次需要使⽤这些partition时,需要从磁盘上读取。

  (3)MEMORY_ONLY_SER:同MEMORY_ONLY,但是会使⽤Java序列化⽅式,将Java对象序列化后进⾏持久化。可以减少内存开销,但是需要进⾏反序列化,因此会加⼤CPU开销。

  (4)MEMORY_AND_DSK_SER:同MEMORY_AND_DSK,但是使⽤序列化⽅式持久化Java对象。

  (5)DISK_ONLY:使⽤⾮序列化Java对象的⽅式持久化,完全存储到磁盘上。

  (6)MEMORY_ONLY_2/MEMERY_AND_DISK_2:如果是尾部加了2的持久化级别,表⽰会将持久化数据复⽤⼀份,保存到其他节点,从⽽在数据丢失时,不需要再次计算,只需要使⽤备份数据即可

  DataFrame的cache默认采用 MEMORY_AND_DISK

  RDD 的cache默认方式采用MEMORY_ONLY

    //缓存
    (1)dataFrame.cache  
    (2)sparkSession.catalog.cacheTable(“tableName”)

    //释放缓存
    (1)dataFrame.unpersist  
    (2)sparkSession.catalog.uncacheTable(“tableName”)



5. Cache和CheckPoint


5.1 CheckPoint
  当spark应⽤程序特别复杂,从初始的RDD开始到最后整个应⽤程序完成有很多的步骤,⽽且整个应⽤运⾏时间特别长,这种情况下就⽐较适合使⽤checkpoint功能。对于特别复杂的Spark应⽤,会出现某个反复使⽤的RDD,即使之前持久化过但由于节点的故障导致数据丢失了,没有容错机制,所以需要重新计算⼀次数据。

  Checkpoint 首先会调用 SparkContext 的 setCheckPointDIR()方法, 设置一个容错的文件系统的目录, 比如说 HDFS;然后对 RDD 调用 checkpoint()方法。之后在 RDD 所处的 job 运行结束之后, 会启动一个单独的 job, 来将checkpoint 过的 RDD 数据写入之前设置的文件系统, 进行高可用、 容错的类持久化操作。

  检查点机制是我们在 spark streaming 中用来保障容错性的主要机制, 它可以使 spark streaming 阶段性的把应用数据存储到诸如 HDFS 等可靠存储系统中,以供恢复时使用。 具体来说基于以下两个目的服务:

  1. 控制发生失败时需要重算的状态数。 Spark streaming 可以通过转化图的谱系图来重算状态, 检查点机制则可以控制需要在转化图中回溯多远。

  2. 提供驱动器程序容错。 如果流计算应用中的驱动器程序崩溃了, 你可以重启驱动器程序并让驱动器程序从检查点恢复, 这样 spark streaming 就可以读取之前运行的程序处理数据的进度, 并从那里继续。

5.2 Cache和CheckPoint区别
  1)Cache只是将数据保存在 BlockManager 中, 但是 RDD 的lineage(血缘关系, 依赖关系)是不变的。但是 checkpoint 执行完之后, rdd 已经没有之前所谓的依赖 rdd 了, 而只有一个强行为其设置的 checkpointRDD,checkpoint 之后 rdd 的 lineage 就改变了。

  2)Cache缓存的数据通常存储在磁盘、内存等地方,可靠性低。Checkpoint的数据通常存储在HDFS等容错、高可用的文件系统,可靠性高。

  3)建议对checkpoint()的RDD使用Cache缓存,这样checkpoint的job只需从Cache缓存中读取数据即可,否则需要再从头计算一次RDD。

6 累加器


  Spark累加器(Accumulators)是一种分布式计算中常用的数据聚合工具。它们提供了一种在并行处理中安全地进行计数器和求和等操作的方法。

  Spark累加器分为两类:标准累加器和自定义累加器。

  标准累加器是 Spark 提供的内置累加器,支持在分布式环境下对整数和浮点数进行累加操作。用户可以在任务中对累加器进行累加操作,然后在驱动器程序中读取累加器的值。

  自定义累加器允许用户通过继承AccumulatorV2类来创建自定义的累加器。这使得用户可以支持更复杂的累加器操作,如列表累加器或自定义对象累加器。

  累加器在 Spark 内部使用了一些技巧来确保正确性和高性能。例如,累加器只能通过驱动程序中的任务访问,而不能通过并行任务之间的共享变量访问,因此它们天然地是线程安全的。此外,Spark还会在内部使用有序序列化来确保累加器的正确性。

  以下是一个使用标准累加器的简单示例:

  Spark累加器特点:

  ① 累加器在全局唯一的,只增不减,记录全局集群的唯一状态;

  ② 在executor中修改它,在driver读取;

  ③ executor级别共享的,广播变量是task级别的共享,两个application不可以共享累加器,但是同一个app不同的job可以共享。

  ④ 分布式计算:累加器在分布式计算中被广泛使用,可以在不同节点的计算任务中共享数据。

  ⑤ 只支持数值类型:Spark累加器只支持数值类型,包括整数、浮点数、长整型等等,不支持其他类型,比如字符串、布尔型等等。

  ⑥ 只能进行加法操作:Spark累加器只支持加法操作,不能进行其他运算操作,比如减法、乘法、除法等等。

  ⑦ 惰性求值:累加器的值只在Spark作业执行完成后才能得到,这是因为Spark的计算是惰性求值的。

你可能感兴趣的:(spark,大数据,分布式)