Spark的三种持久化

Spark的持久化有三种,使用时应当选择最合适的哪一个

cache

使用方法如下
    var sprakconf=new SparkConf().setMaster("local").setAppName("log")
    var sc=new SparkContext(sprakconf)

    var linesRdd= sc.textFile("C:\\log.txt")

    linesRdd.cache() 

cache将数据集持久化到内存,这种持久化相当与另一种叫做persist持久化的一级持久化,开发的时候一般不直接用cache,因为如果保存的数据很多,那么很吃内存的,用多了得不偿失

persist

persist,是最常用的持久化方法,一是使用时可选择的持久化方式较多,二是使用之后释放也很方便,一般持久化到内存时,也不直接用cache,而是调用persist无参,使用方法如下
    var sprakconf=new SparkConf().setMaster("local").setAppName("log")
    var sc=new SparkContext(sprakconf)
	
	sc.setCheckpointDir("mydir") //持久化到外部文件系统,要使用persist必须要设置一个物理路径
	
    var linesRdd= sc.textFile("C:\\log.txt")

    linesRdd.persist() //无参时和cache一样
    linesRdd.unpersist()//取消linesRdd的持久化
    linesRdd.persist(StorageLevel.NONE) //调用其他级别

persist持久化通过传入StorageLevel 伴生对象,并指定值,实现持久化,不过官网只给了7中,但是如果你看过源码,你就会发现,persist其实支持12中持久化方式,我考了一份,大家可以看看

值得大家注意的是StorageLevel 已有的12个级别,可以说是成对出现的,区别就在于多了_2,这是副本个数不同的意思,就拿DISK_ONLY ,来说没有_2时持久化的时候只持久化一份,而有_2表示,还有第2份副本,会在spark运行时保存在其他节点上,如果第一个副本所在的子节点由于某种原因,导致第一份副本不能用了,就会启用第二份副本,当然,这种副本格式大家如果有特殊需要可以直接new对象来设置

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(true, true, true, false, 1)
}

源码中StorageLevel 类的伴生类如下

class StorageLevel private(
    private var _useDisk: Boolean,
    private var _useMemory: Boolean,
    private var _useOffHeap: Boolean,
    private var _deserialized: Boolean,
    private var _replication: Int = 1 )
  extends Externalizable

对应的参数意义如下

_useDisk:使用磁盘持久化
_useMemory:使用内存持久化
_useOffHeap:使用堆外存,这是Java虚拟机里面的概念,堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。
_deserialized:使用反序列化,其逆过程序列化(Serialization)是java提供的一种机制,将对象表示成一连串的字节;而反序列化就表示将字节恢复为对象的过程。序列化是对象永久化的一种机制,可以将对象及其属性保存起来,并能在反序列化后直接恢复这个对象
_replication:副本数,默认是一个

总而言之,大家在使用的时候,使用StorageLevel的那种方式都可以

checkpoint

checkpoint严格意义上不是用来作持久化的,它是一个程序的检查点,就好像建造一座大桥一样,检查点就相当于桥边的那些大柱子,它保证了程序在正常运行时不会因为数据被释放而出错

我这样说,可能大家还是觉得这就是持久化,其实说它是持久化,只是因为它保证数据运行的方式很像且确实起到了持久化数据的作用,但是它和持久化有些差别,我们持久化的时候,可以把数据存储到内存或者磁盘中,通常运行完任务时,持久化的东西也就释放了,毕竟持久化只是为了算法中复用数据集时该数据集不出意外不会被释放,也就是说可以说通常持久化的生命周期就是任务进行时

但是checkpoint,严格的说它是一个检查点,它在我们工作中用的时候是专门用来直接对接hdfs,使用Hadoop集群的副本模式和高可用来保证检查点的最高安全性,当然也可以保存在本地磁盘上,总的来说显而易见的它比前面两种持久化高级,而且他的生命周期也是持久形式的,除非你手动rm -rf它,而且有了检查点你会发现,算法不变时,每一次启动任务时间都会节省很多,不过如果你的算法改变了,那么你就必须去手动删除它,不然会报错的

使用方法如下

    var sprakconf=new SparkConf().setMaster("local").setAppName("log")
    var sc=new SparkContext(sprakconf)
    var linesRdd= sc.textFile("C:\\log.txt")
	sc.setCheckpointDir("mydir") //持久化到外部文件系统,我为了演示方便就没写到hdfs,大家自己用的时候写成hdfs的路径就可以了
    linesRdd.checkpoint()

最后提一句,处理checkpoint,其他两种持久化不能持久化到hdfs,大家可以试一试,一是会报错,而是从底层代码逻辑来说也是不支持的

猜你喜欢

转载自blog.csdn.net/dudadudadd/article/details/114102341