RDD的cache缓存
-如果一个RDD需要重复使用,那么需要从头再次执行来获取数据
-RDD对象可以重用,但是数据不可以重用
-RDD通过Cache或者Persist方法讲前面计算的结果缓存,把数据以缓存在JVM的堆内存中
-但是并不是这两方法被调用时立即缓存,而是触发后面的action算子时,该RDD将会被缓存在计算节点的内存中,供后面重用
-cache操作会增加血缘关系,不改变原来的血缘关系
持久化的作用 & 注意点:
1. 数据能够重复使用
2. cache默认持久化的操作,只能将数据保存到内存中
3. 如果想要保存磁盘文件,需要更改存储级别 StorageLevel.DISK_ONLY
4. 持久化操作必须在行动算子执行时完成
5. RDD对象持久化不一定是为了重用数据,有些数据重要的场合也可以使用
源码:
//设置此RDD的存储级别,以便在第一次操作后将其值持久化
//它是经过计算的。只有在RDD没有分配新的存储级别时,才可以使用它来分配新的存储级别已设置存储级别。
//本地检查点是一个例外。
def persist(newLevel: StorageLevel): this.type = {
if (isLocallyCheckpointed) {
// This means the user previously called localCheckpoint(), which should have already
// marked this RDD for persisting. Here we should override the old storage level with
// one that is explicitly requested by the user (after adapting it to use disk).
persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOverride = true)
} else {
persist(newLevel, allowOverride = false)
}
}
/**
* 本质上也是使用 persist
* 使用默认存储级别(“仅限内存”)保存此RDD。
*/
def cache(): this.type = persist()
RDD CheckPoint 检查点:
-通过将RDD中间结果写入到磁盘
-由于血缘依赖过长会造成容错成本过高,这样就不如在中间阶段左检查点容错
-对RDD进行检查点操作并不会马上被执行,必须和执行Action操作才能触发
/**
将此RDD标记为检查点。它将被保存到检查点内的一个文件中
使用“SparkContext#setCheckpointDir”设置的目录,以及对其父目录的所有引用RDD将被删除。
必须在执行任何作业之前调用此函数
在这个RDD上执行。强烈建议将此RDD持久化内存,否则将其保存到文件中需要重新计算。
*/
def checkpoint(): Unit = RDDCheckpointData.synchronized {
// NOTE: we use a global lock here due to complexities downstream with ensuring
// children RDD partitions point to the correct parent partitions. In the future
// we should revisit this consideration.
if (context.checkpointDir.isEmpty) {
throw new SparkException("Checkpoint directory has not been set in the SparkContext")
} else if (checkpointData.isEmpty) {
checkpointData = Some(new ReliableRDDCheckpointData(this))
}
}
缓存机制和检查点机制的区别和联系:
联系:两者都是做RDD持久化的
区别:
cache:
Cache缓存只是将数据保存起来,数据通常存储在磁盘、内存等地方,可靠性差;
不会截断血缘关系,使用计算过程中的数据缓存
checkpoint:
ck的数据通常存储在HDFS等高可用、容错性好的文件系统;
截断血缘关系,在checkpoint之前必须没有任何任务提交才会生效,ck过程会额外提交一次任务
建议对ck的RDD使用Cache缓存,联合使用效果更好