Spark可以将RDD持久化到内存或磁盘文件系统中,默认情况下,spark将数据存于内存中,这样提高迭代计算以及各计算模型之间的数据共享,同时也带来了一定的风险性。
一般情况下执行节点60%内存用于缓存数据,剩下的40%用于运行任务。
什么情况下需要对数据进行持久化
(1)某步骤计算特别耗时,重新计算的代价较高,所以进行持久化
(2)计算链条特别长的情况下,重新计算的代价也较高
(3)checkpoint所在的RDD也一定要持久化数据,checkpoint是lazy的,框架本身会对checkpoint的RDD触发新的job,不进行persist的话,进行checkpoint的时候数据就会重新计算一遍,所以checkpoint之前一定要进行 persist,因为在checkpoint前有了persist的前提下,计算过一遍之后,再进行计算的时候计算速度非常快
(4)shuffle操作之后,因为shuffle要进行网络传输,网络传输风险大,数据极易丢失,所以shuffle之前进行persist避免数据丢失
(5)shuffle操作之前,框架默认帮助我们把数据持久化到本地磁盘,该步骤由框架自动完成
缓存级别的划分
缓存级别的选择
1:如果你的RDD适合默认的存储级别(MEMORY_ONLY),就选择默认的存储级别。因为这是cpu利用率最高的选项,会使RDD上的操作尽可能的快。
2:如果不适合用默认的级别,选择MEMORY_ONLY_SER。选择一个更快的序列化库提高对象的空间使用率,但是仍能够相当快的访问。
3:除非函数计算RDD的花费较大或者它们需要过滤大量的数据,不要将RDD存储到磁盘上,否则,重复计算一个分区就会和重磁盘上读取数据一样慢。
4:如果你希望更快的错误恢复,可以利用重复存储级别。所有的存储级别都可以通过重复计算丢失的数据来支持完整的容错,但是重复的数据能够使你在RDD上继续运行任务,而不需要重复计算丢失的数据
persist()
persist():RDD[]
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
默认使用
MEMORY_ONLY
这个缓存级别persist(level:StorageLevel):RDD[T]
根据不用的缓存级别对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)
}
}
cache()
def cache(): this.type = persist()
cache()方法使用了默认的存储级别—StorageLevel.MEMORY_ONLY将RDD缓存在内存中
unpersist()
def unpersist(blocking: Boolean = true): this.type = {
logInfo("Removing RDD " + id + " from persistence list")
sc.unpersistRDD(id, blocking)
storageLevel = StorageLevel.NONE
this
}
清除缓存操作