当缓存的(仅限于内存的持久性)数据不适合内存时,spark如何处理内存不足错误?

pgky5nke  于 2021-05-27  发布在  Spark
关注(0)|答案(1)|浏览(403)

我对spark还不熟悉,但我无法找到一个明确的答案:当缓存的数据不适合内存时会发生什么?
在很多地方,我发现如果rdd不适合内存,那么一些分区就不会被缓存,并且会在每次需要时被动态地重新计算。
为了example:lets say 创建了500个分区,假设200个分区没有缓存,那么我们必须通过重新计算rdd来重新计算剩余的200个分区。
如果是这样的话,那么oom错误永远不会发生,但它确实发生了。原因是什么?
请详细解释,谢谢

rkttyhzu

rkttyhzu1#

在spark中,可以使用不同的方法持久化Dataframe。
1) 持久(仅限于内存)
当您仅使用内存\持久化Dataframe时,它将作为反序列化的java对象缓存在spark.cached.memory节中。如果rdd不适合内存,则某些分区将不会被缓存,并且每次需要时都会动态重新计算。这是默认级别,当rdd太大且无法放入内存时,有时会导致oom(也可能在重新计算之后发生)。
回答你的问题
如果是这样的话,那么oom错误永远不会发生,但它确实发生了。原因是什么?即使在重新计算之后,您也需要在内存中匹配这些rdd。如果没有可用的空间,那么gc将尝试清理某个部分并尝试分配它。如果没有成功,那么它将失败
2) 持久(内存和磁盘)
当使用内存\和\磁盘持久化Dataframe时,它将作为反序列化的java对象缓存在spark.cached.memory节中。如果堆中没有可用的内存,那么它将溢出到磁盘。为了解决内存问题,它会将部分数据或完整数据溢出到磁盘(注意:确保节点中有足够的磁盘空间(否则不会弹出磁盘空间错误)
3) persist(memory\u only\u ser)当使用memory\u only\u ser持久化Dataframe时,它将作为序列化的java对象(每个分区一个字节数组)缓存在spark.cached.memory节中。这通常比只使用内存\更节省空间,但这是一项cpu密集型任务,因为涉及压缩(这里的一般建议是使用kyro进行序列化),但这仍然面临类似于只使用内存\的oom问题。
4) persist(memory_和磁盘)它与memory_only_ser类似,但一个区别是当没有堆空间可用时,它会将rdd数组溢出到磁盘,与(memory_和磁盘)相同。。。当您对磁盘空间有严格限制并且希望减少io流量时,我们可以使用此选项。
5) persist(仅限于磁盘\)在这种情况下,不使用堆内存。rdd被持久化到磁盘。确保有足够的磁盘空间,此选项将有巨大的io开销。当您有重复使用的Dataframe时,不要使用此选项。
6) persist(仅内存\u 2或内存\u和磁盘\u 2)这些类似于上面提到的仅内存\u和内存\u和磁盘。唯一的区别是这些选项复制两个集群节点上的每个分区只是为了安全起见。。使用spot示例时,请使用这些选项。
7) 持久(离堆)离堆内存通常包含线程堆栈、spark容器应用程序代码、网络io缓冲区和其他操作系统应用程序缓冲区。甚至您也可以利用ram中的这部分内存来使用上述选项缓存rdd。

相关问题