当缓存(MEMORY_ONLY持久性)的数据无法放入内存时,Spark如何处理内存溢出错误?

5

我是Spark的新手,无法找到明确的答案来解释当缓存的数据无法放入内存时会发生什么?

在许多地方,我发现如果RDD无法放入内存,则某些分区将不会被缓存并且每次需要它们时都会重新计算。

例如:假设创建了500个分区,并且有200个分区未被缓存,则必须通过重新评估RDD来重新计算剩余的200个分区。

如果情况是这样的,那么就不应该发生OOM错误,但实际上确实会发生。原因是什么?

非常感谢详细的解释。

1个回答

5
在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) 堆外内存通常包含线程堆栈、Spark容器应用程序代码、网络IO缓冲区和其他OS应用程序缓冲区。即使你可以从RAM中利用此部分内存来缓存RDD,也可以使用以上选项。

1
感谢您详细解释了“Persist (MEMORY_ONLY)”功能。 - Santhosh reddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接