San*_*ddy 5 caching partitioning out-of-memory apache-spark rdd
我是 Spark 新手,无法找到明确的答案:当缓存的数据不适合内存时会发生什么?
我在很多地方发现,如果 RDD 不适合内存,某些分区将不会被缓存,并且会在每次需要时动态重新计算。
例如:假设创建了 500 个分区,并假设 200 个分区没有缓存,那么我们必须通过重新评估 RDD 来重新计算剩余的 200 个分区。
如果是这种情况,那么 OOM 错误本不应该发生,但它却发生了。原因是什么?
非常感谢详细的解释。提前致谢
您可以通过多种方式在 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) Persist (MEMORY_AND_DISK_SER) 它与 MEMORY_ONLY_SER 类似,但一个区别是当没有可用堆空间时,它会将 RDD 数组溢出到磁盘,与 (MEMORY_AND_DISK) 相同...当您有严格约束时,我们可以使用此选项磁盘空间,并且您希望减少 IO 流量。
5)持久化(DISK_ONLY) 在这种情况下,不使用堆内存。RDD 被持久化到磁盘。确保有足够的磁盘空间,此选项将产生巨大的 IO 开销。当您有重复使用的数据帧时,请勿使用此选项。
6) Persist (MEMORY_ONLY_2 或 MEMORY_AND_DISK_2) 这些与上面提到的 MEMORY_ONLY 和 MEMORY_AND_DISK 类似。唯一的区别是这些选项复制两个集群节点上的每个分区只是为了安全起见。当您使用 Spot 实例时,请使用这些选项。
7)Persist(OFF_HEAP) 堆外内存一般包含线程堆栈、spark容器应用程序代码、网络IO缓冲区和其他OS应用程序缓冲区。即使您可以通过上述选项利用 RAM 中的这部分内存来缓存 RDD。