首页 > 解决方案 > Spark 如何处理部分缓存/持久化结果?

问题描述

如果您缓存一个无法全部存储在内存或磁盘中的非常大的数据集,Spark 如何处理部分缓存?当您再次使用该数据框时,它如何知道需要重新计算哪些数据?

例子:

  1. 将 100 GB 数据集读入内存df1
  2. df2基于计算新的数据帧df1
  3. 缓存df2

如果 spark 只能容纳 50GB 的缓存,df2那么如果您要重用df2后续步骤会发生什么?spark如何知道哪些数据不需要重新计算,哪些需要重新计算?它是否需要再次重新读取无法持久的数据?

更新

如果您有 5GB 内存和 5GB 磁盘并尝试缓存 20GB 数据集会怎样?无法缓存的其他 10GB 数据会发生什么情况,Spark 如何知道哪些数据需要重新计算,哪些不需要?

标签: apache-spark

解决方案


Spark为 DF 和 DS提供了这个默认选项:

MEMORY_AND_DISK – 这是 DataFrame 或 Dataset 的默认行为。在这个 Storage Level 中,DataFrame 将作为反序列化对象存储在 JVM 内存中。当所需存储空间大于可用内存时,它将一些多余的分区存储到本地磁盘中,并在需要时从本地磁盘读取数据。由于涉及 I/O,因此速度较慢。

但是,更具体地说:

Spark 的处理单元是一个 partition = 1 个任务。所以讨论更多的是关于适合内存和/或本地磁盘的分区。

如果在使用 StorageLevel.MEMORY_AND_DISK 时 DF 的一个分区不适合内存和磁盘,那么操作系统将失败,也就是杀死 Executor / Worker。可能会驱逐除您自己的 DF 之外的其他分区,但不会针对您自己的 DF。无论成功与否,在这种.cache情况下都没有重读。

我基于这样一个事实,即属于同一底层 RDD 的分区不会发生分区驱逐。没有很好地解释所有这些东西,但请参阅此处:Spark 如何驱逐缓存的分区?. 最后,其他 RDD 分区可能会被驱逐并重新计算,但最后你还需要足够的本地磁盘和内存。

一个很好的阅读是:https ://sparkbyexamples.com/spark/spark-difference-between-cache-and-persist/


推荐阅读