Spark Databricks中MEMORY_AND_DISK缓存占比执行Action后下降问题
问题原因分析
Spark的MEMORY_AND_DISK缓存策略并非严格优先保留内存数据,以下是导致该现象的核心逻辑:
- LRU淘汰的主动触发:Spark BlockManager的LRU(最近最少使用)算法不仅在内存不足时触发,当执行Job9这类产生临时中间块的作业时,即使总内存有剩余,BlockManager也可能为新临时块腾空间,优先淘汰访问频率低的持久化块——哪怕该块仅50MB。
- 分区粒度的影响:若DataFrame分区较多,每个分区对应独立缓存块,Job9执行时部分分区块可能被标记为“冷数据”,BlockManager会单独刷盘这些小分区,而非整体保留缓存。
- Databricks内存预留差异:Ganglia显示的“可用内存”未扣除Driver、系统进程或集群动态预留的内存,实际供BlockManager使用的缓存内存可能低于预期,间接触发部分块刷盘。
替代解决方案(除写入临时存储外)
- 设置缓存优先级:使用
persist(StorageLevel.MEMORY_AND_DISK.withPriority(10))(优先级数值越高越优先),让BlockManager在淘汰时优先保留目标DataFrame的缓存块。 - 切换序列化存储级别:改用
MEMORY_ONLY_SER或MEMORY_AND_DISK_SER,序列化后的缓存块内存占用更小,相同内存可容纳更多块,降低临时块触发淘汰的概率;建议搭配Kryo序列化提升效率。 - 强制缓存并锁定状态:在Job6执行完成后,执行
df.count()强制全量缓存写入内存,再通过spark.sparkContext.getPersistentRDDs定位对应RDD,重新调用rdd.persist(StorageLevel.MEMORY_AND_DISK)确认存储级别,避免后续操作干扰缓存状态。 - 调整Spark内存配置:
- 提高
spark.memory.fraction(默认0.6):扩大缓存与执行内存的总占比,给缓存分配更多空间。 - 提高
spark.memory.storageFraction(默认0.5):提升缓存内存在“执行+缓存”总内存中的占比,减少缓存块被淘汰的可能。
- 提高
- 主动标记缓存为热数据:在Job9执行前后,执行轻量操作(如
df.rdd.isEmpty())访问缓存DataFrame,让BlockManager将这些块标记为“常用”,降低LRU淘汰优先级。
内容的提问来源于stack exchange,提问作者Sushant Pachipulusu
相关产品推荐
相关产品推荐

