您可以通过多种方式在 spark 中持久化数据帧。
1)持久化 (MEMORY_ONLY)
当您使用 MEMORY_ONLY 持久化数据帧时,它将作为反序列化的 Java 对象缓存在 spark.cached.memory 部分中。如果 RDD 不适合内存,则某些分区将不会被缓存,并且会在每次需要时重新计算。这是默认级别,当 RDD 太大而无法放入内存时,有时会导致 OOM(在重新计算后也可能发生)。
回答你的问题
如果是这种情况,那么 OOM 错误应该永远不会发生,但它确实发生了。原因是什么?
即使在重新计算之后,您也需要将这些 rdd 放入内存中。如果没有可用空间,则 GC 将尝试清理某些部分并尝试分配它。如果不成功,则它将因 OOM 失败
2)持久化 (MEMORY_AND_DISK)
当您使用 MEMORY_AND_DISK 持久化数据帧时,如果内存在堆中不可用,它将作为反序列化的 Java 对象缓存在 spark.cached.memory 部分中,然后它将溢出到磁盘。为了解决内存问题,它会将部分数据或完整数据溢出到磁盘。 (注意:确保节点有足够的磁盘空间,否则会弹出无磁盘空间错误)
3)坚持 (MEMORY_ONLY_SER)
当您使用 MEMORY_ONLY_SER 持久化数据帧时,它将作为序列化 Java 对象(每个分区一个字节数组)缓存在 spark.cached.memory 部分中。这通常比 MEMORY_ONLY 更节省空间,但它是一项 cpu 密集型任务,因为涉及压缩(这里一般建议使用 Kyro 进行序列化)但这仍然面临类似于 MEMORY_ONLY 的 OOM 问题。
4)持久化 (MEMORY_AND_DISK_SER)
它类似于 MEMORY_ONLY_SER 但一个区别是当没有可用的堆空间时,它会将 RDD 数组溢出到与 (MEMORY_AND_DISK) 相同的磁盘...当您对磁盘空间有严格限制并且想要减少 IO 流量。
5)持久化 (DISK_ONLY)
在这种情况下,不使用堆内存。RDD 被持久化到磁盘。确保有足够的磁盘空间,这个选项会产生巨大的 IO 开销。当你有重复使用的数据框时,不要使用它。
6)持久化(MEMORY_ONLY_2 或 MEMORY_AND_DISK_2)
这些类似于上面提到的 MEMORY_ONLY 和 MEMORY_AND_DISK。唯一的区别是这些选项在两个集群节点上复制每个分区只是为了安全起见。在使用 Spot 实例时使用这些选项。
7)坚持 (OFF_HEAP)
堆外内存通常包含线程堆栈、火花容器应用程序代码、网络 IO 缓冲区和其他 OS 应用程序缓冲区。甚至你也可以通过上述选项利用 RAM 中的这部分内存来缓存你的 RDD。