1. 缓存基础:什么是Spark缓存?为什么需要缓存?缓存与持久化的区别

各位同学好,我是老张。做Spark优化这些年,我见过太多人一上来就调参数、改代码,结果性能没提上去,反而把集群搞崩了。其实,缓存才是性价比最高的优化手段之一。今天咱们就把缓存这件事彻底聊透。

1.1 什么是Spark缓存?

说白了,Spark缓存就是把某个RDD或DataFrame的计算结果,主动存到内存(或磁盘)里,后续再用的时候直接拿,不用重新算一遍。

举个例子。你写了一段ETL逻辑,从HDFS读原始日志,经过清洗、过滤、关联维表,得到一个中间结果集。后面你要对这个结果做三次不同的聚合分析。如果不加缓存,Spark会老老实实把前面那套流程重复执行三遍。加上缓存,它就只算一次,后面直接复用。

核心思想:缓存是「以空间换时间」——用额外的存储开销,换取重复计算的时间节省。

我个人习惯把缓存理解成「快照」。你在某个计算节点拍一张照片,后面所有操作都基于这张照片,而不是重新演一遍电影。

1.2 为什么需要缓存?

这个问题我问过不少刚入行的同学,答案五花八门。其实核心原因就三个:

  • 避免重复计算——这是最直接的收益。一个DAG里,如果某个Stage被多个下游依赖,不加缓存就是重复劳动。
  • 提升交互式查询速度——做Ad-hoc分析时,同一个数据集可能要反复查询。缓存后响应时间能从分钟级降到秒级。
  • 缓解Shuffle压力——有些场景下,缓存可以替代部分Shuffle操作,减少网络传输和磁盘IO。

我在项目中遇到过这样一个案例:一个实时数仓的ETL任务,每天跑两个小时。加了缓存之后,直接缩到40分钟。你想想看,同样的集群资源,产出时间缩短了三分之二,老板能不高兴吗?

小提示:缓存不是万能的。如果某个RDD只被用一次,缓存反而浪费资源。判断标准很简单——看它被引用的次数,引用次数 ≥ 2 才值得缓存。

1.3 缓存与持久化的区别

这个问题经常被问到,也是面试高频题。很多同学以为缓存和持久化是一回事,其实不然。

先看代码。Spark里缓存和持久化的调用方式:

// 缓存
df.cache()

// 持久化
df.persist(StorageLevel.MEMORY_AND_DISK)

你发现没有?cache() 其实等价于 persist(StorageLevel.MEMORY_ONLY)。所以从API层面看,cache是persist的一个特例。

但它们的区别不止于此。我整理了一张表,看完你就明白了:

对比维度 cache() persist()
存储级别 固定为 MEMORY_ONLY 可自定义(内存、磁盘、堆外、序列化等)
灵活性 低,只能存内存 高,支持多种组合
适用场景 数据量小,内存充足 数据量大,或需要容错保障
底层实现 调用 persist(MEMORY_ONLY) 直接调用 StorageLevel 参数

嗯,这里要注意:cache() 虽然简单,但风险也大。如果数据量超过可用内存,Spark会直接OOM,或者频繁GC把性能拖垮。我曾经在一个日志分析项目里,就因为图省事用了cache(),结果凌晨三点被电话叫醒——集群挂了。

避坑指南:生产环境里,我建议优先用 persist() 并指定 MEMORY_AND_DISK 或 MEMORY_AND_DISK_SER。这样内存不够时能 spill 到磁盘,至少不会崩。别问我怎么知道的——都是血泪教训。

1.4 缓存的核心流程

为了让你更直观地理解缓存的工作机制,我画了一张流程图:

Spark 缓存核心流程 原始 RDD / DataFrame 计算过程(Transformation) 调用 cache() / persist() 存储到内存 存储到磁盘 缓存数据块 缓存数据块 后续 Action 直接读取缓存,跳过重复计算 cache() 默认存内存 persist() 可指定存储级别

从图上你能看到,缓存的核心决策点在于存储级别的选择。选对了,性能翻倍;选错了,要么内存溢出,要么磁盘IO拖慢速度。

1.5 什么时候不该用缓存?

说了这么多缓存的好处,我也得泼点冷水。不是所有场景都适合缓存。我总结了几种「缓存反模式」:

  • 数据只用一次——比如只做一次count(),缓存纯属浪费。
  • 数据量远大于可用内存——硬缓存会导致频繁spill,比不缓存还慢。
  • 数据频繁更新——缓存的数据很快失效,得不偿失。
  • 小数据集——几KB的数据,重新计算比从缓存读取还快。

我的建议:每次加缓存之前,先问自己三个问题——这个数据被用几次?内存够不够?数据会不会变?三个问题都过了,再动手。

好了,这一章的内容就到这里。缓存是Spark性能优化的第一把钥匙,后面我们会深入各种存储级别的细节,以及如何在实际项目中用好缓存。记住一句话:缓存不是银弹,但用对了就是核弹。