RDD持久化(缓存)

Spark RDD 是惰性求值的,而有时我们希望能多次使用同一个 RDD。如果简单地对 RDD 调用行动操作,Spark 每次都会重算 RDD 以及它的所有依赖。这在迭代算法中消耗格外大,因为迭代算法常常会多次使用同一组数据。

比如下面就是先对 RDD 作一次计数、再把该 RDD 输出的一个小例子。

val result = input.map(x => x*x)

println(result.count())

println(result.collect().mkString(","))

为了避免多次计算同一个 RDD,可以让 Spark 对数据进行持久化。当我们让 Spark 持久化存储一个 RDD 时,计算出 RDD 的节点会分别保存它们所求出的分区数据。如果一个有持久化数据的节点发生故障,Spark 会在需要用到缓存的数据时重算丢失的数据分区。如果希望节点故障的情况不会拖累我们的执行速度,也可以把数据备份到多个节点上

出于不同的目的,我们可以为 RDD 选择不同的持久化级别(如下表)。在 Scala和 Java 中,默认情况下 persist() 会把数据以序列化的形式缓存在 JVM 的堆空间中。在 Python 中,我们会始终序列化要持久化存储的数据,所以持久化级别默认值就是以序列化后的对象存储在 JVM 堆空间中。当我们把数据写到磁盘或者堆外存储上时,也总是使用序列化后的数据。

持久化级别:

 RDD持久化(缓存)_第1张图片

RDD持久化(缓存)_第2张图片 

检查点checkpoint:

RDD能够在第一次计算完之后,将计算结果保存到内存、本地文件系统或者HDFS中。通过缓存,Spark避免了RDD上的重复计算,能够极大地提高计算速度。但是如果缓存丢失了,则需重新计算。如果计算特别复杂或者计算特别耗时,那么缓存丢失对于整个job的影响是不容忽视的。为了避免缓存丢失重新计算带来的开销,Spark有引入了检查点(checkpoint)机制。

checkpoint将RDD持久化到磁盘,还可以切断RDD之间的依赖关系(这里的意思是,后面的RDD找数据的时候,就可以直接从checkpoint持久化目录里找了)。

checkpoint 的执行原理:

(1)当RDD的job执行完毕后,会从finalRDD从后往前回溯。

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

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

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

使用:


public class Demo04CheckPoint {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("test");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD lines = sc.textFile("./word");
sc.setCheckpointDir("./checkpoint");
lines = lines.cache();
lines.checkpoint();
lines.collect();
sc.stop();
sc.close();
}
}

RDD持久化(缓存)_第3张图片

当然此处只是为了测试,一般我们会把checkpoint持久化的数据存储在HDFS上面。 

你可能感兴趣的:(Spark)