我有一个循环操作,它生成一些RDD,重新分区,然后是aggregatebykey操作。在循环运行之后,它计算最终的RDD,它被缓存并检查点,并且还用作下一个循环的初始RDD。
这些RDD非常大并且在每次迭代到达最终RDD之前会生成大量中间混洗块。我正在压缩我的shuffle并允许shuffle溢出到磁盘。
我注意到我的工作机器上没有清理存储随机文件的工作目录。因此最终我的磁盘空间不足。我的印象是,如果我检查我的RDD,它将删除所有中间shuffle块。然而,这似乎没有发生。任何人都有任何关于如何在循环的每次迭代后清理我的shuffle块的想法,或者为什么我的shuffle块没有被清理?
答案 0 :(得分:1)
将RDD缓存到内存/磁盘后,只要spark上下文处于活动状态,RDD就会存储在内存/磁盘中。
为了告诉驱动程序它可以从内存/磁盘中删除RDD,您需要使用unpersist()
功能。
来自
java-doc
:/** * Mark the RDD as non-persistent, and remove all blocks for it from memory and disk. * * @param blocking Whether to block until all blocks are deleted. * @return This RDD. */ def unpersist(blocking: Boolean = true)
所以你可以使用:
rdd.unpersist()
答案 1 :(得分:1)
取决于您是否在这些RDD之间存在依赖关系。例如:
val rdd2 = rdd1.<transformation>
val rdd3 = rdd2.<transformation>
...
这种情况下,火花将记住血统,并且将始终存在对旧RDD的引用,这使得它不被火花驱动器清理(火花驱动器上的gc火花rdd清理被gc放下来回收一旦他们不再被引用,一些rdd引用。)
所以persist()在这种情况下不会工作,唯一的方法是使用localCheckpoint()
。这就是我以前做过的,并为我工作过:
rdd.persist(StorageLevel.MEMORY_AND_DISK_2)
.localCheckpoint()
// do sth here and later
rdd.unpersist()
这使得火花正确地截断了血统,然后你可以安全地unpersist()它而不用担心未清洁的参考。
请参阅spark doc,了解如何正确截断执行计划沿袭:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/spark-rdd-checkpointing.html