Spark缓存级别

在spark中,如果一个rdd或者Dataset被多次复用,最好是对此做缓存操作,以避免程序多次进行重复的计算。Spark 的缓存具有容错机制,如果一个缓存的 RDD 的某个分区丢失了,Spark 将按照原来的计算过程,自动重新计算并进行缓存。

缓存的使用:

val dataset = spark.read.parquet(file)
	dataset.cache()
	或者:dataset.persist()

cache() 跟 persist() 实际上是一样的,都是MEMORY_AND_DISK级别。

如果想要控制缓存级别,则需要在persist()中加上你需要缓存的级别,如:

dataset.persist(StorageLevel.MEMORY_ONLY)

缓存的释放:

dataset.unpersist()
dataset.unpersist(true) //true 指定的是是否阻塞进程,直到所有block都被删除。

注意:如果要对某个缓存进行释放,要在action操作之后,不然该缓存是无效的。

缓存级别:

级别

使用空间

CPU时间

是否在内存中

是否在磁盘上

备注

MEMORY_ONLY





MEMORY_ONLY_2





数据存2份

MEMORY_ONLY_SER_2





数据序列化,数据存2份

MEMORY_AND_DISK


中等

部分

部分

如果数据在内存中放不下,则溢写到磁盘

MEMORY_AND_DISK_2


中等

部分

部分

数据存2份

MEMORY_AND_DISK_SER



部分

部分

MEMORY_AND_DISK_SER_2



部分

部分

数据存2份

DISK_ONLY





DISK_ONLY_2





数据存2份

NONE

OFF_HEAP

上面列表上的所有级别都是在org.apache.spark.storage.StorageLevel类中

如何选择存储级别

Spark 的存储级别的选择,核心问题是在内存使用率和 CPU 效率之间进行权衡。建议按下面的过程进行存储级别的选择 :

  • 如果使用 MEMORY_ONLY 存储在内存中的 RDD / DataFrame 没有发生溢出,那么就选择默认的存储级别。默认存储级别可以最大程度的提高 CPU 的效率,可以使在 RDD / DataFrame 上的操作以最快的速度运行。
  • 如果内存不能全部存储 RDD / DataFrame ,那么使用 MEMORY_ONLY_SER,并挑选一个快速序列化库将对象序列化,以节省内存空间。使用这种存储级别,计算速度仍然很快。
  • 除了在计算该数据集的代价特别高,或者在需要过滤大量数据的情况下,尽量不要将溢出的数据存储到磁盘。因为,重新计算这个数据分区的耗时与从磁盘读取这些数据的耗时差不多。
  • 如果想快速还原故障,建议使用多副本存储级别 MEMORY_ONLY_2 / MEMORY_ONLY_SER_2 。所有的存储级别都通过重新计算丢失的数据的方式,提供了完全容错机制。但是多副本级别在发生数据丢失时,不需要重新计算对应的数据库,可以让任务继续运行。