Spark缓存-persist和cache方法
在 Spark 中,persist 和 cache 方法都用于将 RDD(弹性分布式数据集)或 DataFrame 持久化,以避免重复计算从而提升性能,但二者存在一些区别。
1. 功能本质
persist:这是一个通用的持久化方法,能够指定多种不同的存储级别。存储级别决定了数据的存储位置(如内存、磁盘)以及存储形式(如是否序列化)。
cache:其实是 persist 方法的一种特殊情况,它等价于调用 persist(StorageLevel.MEMORY_ONLY),也就是将数据以非序列化的 Java 对象形式存储在内存中。
2. 存储级别指定
persist:可以通过传入 StorageLevel 参数来指定不同的持久化级别。常见的持久化级别有:
MEMORY_ONLY:将 RDD 以 Java 对象的形式存储在 JVM 的内存中。若内存不足,部分分区将不会被缓存,需要时会重新计算。
MEMORY_AND_DISK:优先把 RDD 以 Java 对象的形式存储在 JVM 的内存中。若内存不足,会把多余的分区存储到磁盘上。
DISK_ONLY:将 RDD 的数据存储在磁盘上。
MEMORY_ONLY_SER:将 RDD 以序列化的 Java 对象形式存储在内存中,相较于 MEMORY_ONLY,序列化后占用的内存空间更小,但读取时需要进行反序列化操作,会带来一定的性能开销。
MEMORY_AND_DISK_SER:优先将 RDD 以序列化的 Java 对象形式存储在内存中,内存不足时存储到磁盘上。
cache:不能指定存储级别,它固定使用 MEMORY_ONLY 存储级别。
常见存储级别
存储级别 | 说明 |
---|---|
MEMORY_ONLY | 默认,纯内存存储(Java 对象),速度最快。 |
MEMORY_ONLY_SER | 内存存储(序列化后),节省空间但需反序列化(推荐!)。 |
MEMORY_AND_DISK | 优先内存,不足时溢写到磁盘(Java 对象)。 |
MEMORY_AND_DISK_SER | 优先内存(序列化),不足时溢写到磁盘(推荐!)。 |
DISK_ONLY | 纯磁盘存储,适用于超大数据集。 |
OFF_HEAP | 堆外内存(Tungsten 优化),减少 GC 压力。 |
缓存 vs. 检查点(Checkpoint)
特性 | 缓存 (Cache/Persist) | 检查点 (Checkpoint) |
---|---|---|
存储位置 | 内存或磁盘(executor 节点) | 可靠存储(如 HDFS) |
血统(Lineage) | 保留,可通过重新计算恢复丢失数据 | 截断,检查点后不再依赖原始 RDD |
成本 | 低(仅存储计算结果) | 高(需写入外部存储) |
用途 | 加速多次使用的中间结果 | 长期保存关键数据(如迭代算法的状态) |
persist的示例
下面我们以DISK_ONLY为例,改写上面的程序,验证它的持久化效果。具体要改动的地方有两个: 指定持久化地址; 把cache改成persist;
conf.set("spark.local.dir", "/path/to/your/local/dir")
sc = SparkContext(conf)val cachedRDD = largeRDD.map(complexTransformation).persist(StorageLevel.MEMORY_ONLY)
总结
- 缓存是提升 Spark 性能的关键手段,尤其适合迭代计算和交互式分析。
cache()
是简化版的persist()
,默认存储在内存。- 合理选择存储级别(如
MEMORY_ONLY_SER
)可显著节省内存并提升效率。 - 避免过度缓存:只缓存真正需要复用的数据,防止内存溢出。