spark-内存管理-缓存机制

什么是持久化?暂时的东西永久保存就是持久化,在计算机中,就是内存里的东西落到磁盘上。

概念

RDD持久化,持久化的单位是partition

因为RDD不存数据,它的数据都在partition上。

控制、持久化算子有三种,cache,persist,checkpointcachepersist都是执行的。必须有一个action类算子触发执行。checkpoint算子不仅能将RDD持久化到磁盘,还能切断RDD之间的依赖关系

前2个调优,第三个容错。

cache

在一些计算中,DAG有可能会很长,某些RDD可能会被多个子RDD使用,每使用一次就会触发一次完整的计算,所以可以把这个父RDD缓存,这样就不用每次都计算了

rdd.cache
  • 可以在sparkUI中对应application的detail ui/storage中查看缓存情况

底层调用的是persist(StorageLevel.MEMORY_ONLY)
其中持久化级别有7种

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)
  ……
}

persist

持久化的时候,如果内存不够用咋办?可否像MR那样溢写到磁盘

可以指定持久化的级别。最常用的是MEMORY_ONLYMEMORY_AND_DISK

持久化级别如下:

在这里插入图片描述

上面这些带有_2的表示有副本replication

序列化会把对象转成字节数组,更加节省空间。但byte[]但消耗性能,类似于压缩文件。

cachepersist的注意事项:

  1. cachepersist都是懒执行,必须有一个action类算子触发执行。
  2. cachepersist算子的返回值可以赋值给一个变量,在其他job中直接使用这个变量就是使用持久化的数据了。持久化的单位是partitionRDD的组成)。
  3. cachepersist算子后不能立即紧跟action算子。

跑一下disk_ONLY,落盘落到哪里呢?反正不是在项目工作空间下,在哪呢?不重要,它也压根不想让你知道,因为你不需要知道,本质就是个调优手段。下次需要这个RDD的数据,会自动去找。但如果想要容错,那就需要知道存在哪呢,这就要用到容错的算子,专业的事让专业的人来干,也就是我们的checkpoint算子。

checkpoint

cache只能避免重复计算,但如果是节点宕机导致数据丢失,那cache就无效了,此时仍然需要根据lineage(血统)重新计算,如果在这之前有100个rdd,那么在要经过100次的转换,效率很低。
checkpoint的作用就是将DAG中比较重要的中间数据存储到一个高可用的地方(通常是hdfs),同时切断之前的血缘,使用数据时直接从checkpoint的目录中取,这样即安全又避免了重复计算。

all references to its parent RDDs will be removed.

执行checkpoint后这个rdd之前所有的依赖关系会被移除掉,再进行计算时,直接从这个hdfs目录中去读取数据,而不需要再根据rdd的依赖关系去重新计算。

usage

  1. 如果在hdfs上设置,会在指定的目录下创建1个uuid为名的目录,里面按分区保存了对应RDD分区的数据,RDD有几个分区,这个目录下就有几个文件
  2. 因为执行checkpoint时会从头计算,这样就跟之前的计算重复了,所以文档中推荐在执行rdd.checkpoint之前先cache,也就是rdd.cache.checkpoint
  3. 使用sc来设置cp目录
    sc.setCheckpointDir("hdfs://master:9000/checkpoint") 
    
  4. 要缓存的rdd执行rdd.checkpoint,checkpoint也是lazy的,但checkpoint不是transformation,只是RDD的1个函数

这个名字起的其实很贴切,我们以前玩单机游戏的时候,会有存档的概念,存档对应的单词就是这个词,这样我们下次就可以直接从存档处开始玩。所以checkpoint就意味着要落盘,可以直接从存档处开始执行。

checkpointRDD持久化到磁盘,还可以切断RDD之间的依赖关系,也是懒执行。

执行原理:

在这里插入图片描述

  1. RDDjob执行完毕后,会从finalRDD从后往前回溯。

  2. 当回溯到某一个RDD调用了checkpoint方法,会对当前的RDD做一个标记。

  3. Spark框架会自动启动一个新的job,重新计算这个RDD的数据,将数据持久化到HDFS上。

    如果是集群模式,必须是hdfs路径

    读checkpoint方法源码

    ​ 切断血缘

    ​ 在RDD上的所有job都执行完之后才会另起一个job执行checkpoint的操作,所以最好先执行cache,避免重新算==》图

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

demo示例如下:

SparkConf conf = new SparkConf();
conf.setMaster("local").setAppName("checkpoint");
JavaSparkContext sc = new JavaSparkContext(conf);
sc.setCheckpointDir("./checkpoint");
JavaRDD<String> lines = sc.textFile("./NASA_access_log_Aug95");
lines.checkpoint();
lines.count();
jsc.stop();

点开cp的文件,会发现里面都是数据

如果没写setCP这句话,直接执行RDD的cp,会报错

点开官网,查看cp的章节,关于持久化级别的选择,ser、disk尽量不用,还没重新算一遍快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值