spark的持久化

spark的持久化

  • cache
  • persisit
  • checkpoint

    以上算子都可以将RDD持久化,持久化的单位是partition。cache和persist都是懒执行的。必须有一个action类算子触发执行。checkpoint算子不仅能将RDD持久化到磁盘,还能切断RDD之间的依赖关系。

1. cache

默认将RDD的数据持久化到内存中。cache是懒执行。

注意:cache () = persist()
=persist(StorageLevel.Memory_Only)

2. persist

可以指定持久化的级别。最常用的是MEMORY_ONLY和MEMORY_AND_DISK。”_2”表示有副本数。

2.5. cache和persist注意事项

cache和persist注意事项:

  1. cache和persist都是懒执行,必须有一个action类算子触发执行。
  2. cache和persist算子的返回值可以赋值给一个变量,在其他job中直接使用这个变量就是使用持久化的数据了。持久化的单位是partition。
  3. cache和persist算子后不能立即紧跟action算子。
    错误:rdd.cache().count() 返回的不是持久化的RDD,而是一个数值了

3.checkpoint

checkpoint将RDD持久化到磁盘,还可以切断RDD之间的依赖关系。

checkpoint 的执行原理:

  1. 当RDD的job执行完毕后,会从finalRDD从后往前回溯。
  2. 当回溯到某一个RDD调用了checkpoint方法,会对当前的RDD做一个标记。
  3. Spark框架会自动启动一个新的job,重新计算这个RDD的数据,将数据持久化到HDFS上。

    优化:对RDD执行checkpoint之前,最好对这个RDD先执行cache,这样新启动的job只需要将内存中的数据拷贝到HDFS上就可以,省去了重新计算这一步。

4. 源码解读

RDD.scala

 /** Persist this RDD with the default storage level (`MEMORY_ONLY`). */
  def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)

  /** Persist this RDD with the default storage level (`MEMORY_ONLY`). */
  def cache(): this.type = persist()

StorageLevel.scala

class StorageLevel private(
    private var _useDisk: Boolean,  //是否使用磁盘
    private var _useMemory: Boolean,  //是否使用内存
    private var _useOffHeap: Boolean,   //是否使用堆外内存(主要指tachyon)
    private var _deserialized: Boolean,  //是否不序列化
    private var _replication: Int = 1)  //副本数量
  extends Externalizable {
//-----------------------
object StorageLevel {
  val NONE = new StorageLevel(false, false, false, false)
  val DISK_ONLY = new StorageLevel(true, false, false, false)
  val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
  val MEMORY_ONLY = new StorageLevel(false, true, false, true)
  val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
  val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
  val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
  val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
  val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
  val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
  val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
  val OFF_HEAP = new StorageLevel(false, false, true, false)

注意:

  • MEMORY_ONLY :仅当内存能够装下RDD的数据时,才进行持久化到内存
  • MEMORY_AND_DISK :当内存不够时,剩下RDD的数据持久化到磁盘
  • eg: 500M内存,RDD的数据为2G,若为MEMORY_ONLY持久化方式,则因为内存装不下,RDD其所有数据都不会持久化;若为MEMORY_AND_DISK,则会持久化500M的RDD数据到内存,剩下1.5G存储到磁盘

5. Demo

CacheDemo.scala

package com.qiuyang.scala

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkContext, SparkConf}

/**
  * Created by qiuyang on 2018/11/30.
  *
  * 持久化算子
  *   cache/persist/checkpoint,均为懒执行算子,需要Action算子触发执行
  *   三个持久化算子,持久化的单位都是partition
  * 1.cache: 默认将RDD中的数据存储在内存中
  * 2.persist(): 可选择存储方式,persist(StorageLevel.MEMORY_ONLY)=cache()=persist()
  *   *cache和persist注意:
  *     >cache和persist都是懒执行,需要Actio算子触发执行
  *     >对一个RDD cache或persist之后可以赋值给一个变量,下次直接使用这个变量就是使用持久化的RDD
  *     >如果赋值给一个变量,那么cache和persist之后不能紧跟Action算子
  * 3.checkponit: 会封装job执行
  *
  */
object CacheDemo {
  def main(args: Array[String]) {
    val conf: SparkConf = new SparkConf()
    conf.setAppName("CacheDemo").setMaster("local")
    val sc: SparkContext = new SparkContext(conf)

    var lines: RDD[String] = sc.textFile("/Users/qiuyang/githublib/qiuyang-spark-scala/src/word")

//    val count1: Long = lines.filter(_.equals("hello scala")).count()
//    val count2: Long = lines.filter(!_.equals("hello scala")).count()
//    println("number of \"hello scala\":"+count1)
//    println("others:"+count2)

    val start: Long = System.currentTimeMillis()
    val count1: Long = lines.count()
    val end: Long = System.currentTimeMillis()
    println("count1 = "+count1+", time1 = "+(end-start)+"ms")

    lines = lines.cache()

    val start2: Long = System.currentTimeMillis()
    val count2: Long = lines.count()
    val end2: Long = System.currentTimeMillis()
    println("count2 = "+count2+", time2 = "+(end2-start2)+"ms")
    sc.stop()
  }

}

CheckPonitDemo.scala

package com.qiuyang.scala

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by qiuyang on 2018/11/30.
  * CheckPoint持久化--会封装一个job
  * 特点:
  *   1.将数据存储再磁盘中,一定要先用sc.setCheckpointDir指定存储路径
  *   2.切断了与前面RDD的联系
  *   3.CheckPoint与persist(StorageLevel.DISK_ONLY)的区别?=>Application运行完后,后者就没了,被回收了,而CheckPoint存储的数据还在
  *   4.某些特定场景,必须用CheckPoint
  *   5.CheckPoint是懒加载,且它会再job执行完成之后,spark自动封装job去执行
  */
object CheckPonitDemo {
  def main(args: Array[String]) {
    val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("checkpointdemo"))

    //设置checkpoint存储数据的位置,可指定为hdfs上的位置,此处指定本地,会自动创建文件夹
    sc.setCheckpointDir("./checkpoint")

    val lines: RDD[String] = sc.textFile("/Users/qiuyang/githublib/qiuyang-spark-scala/src/word")
    lines.checkpoint()

    println(lines.count())
    sc.stop()
  }
}

猜你喜欢

转载自blog.csdn.net/QiuYang18/article/details/84649846