了解Spark的缓存

时间:2015-04-27 18:48:39

标签: apache-spark

我正在努力了解Spark的缓存是如何工作的。

这是我的天真理解,如果我遗失了某些内容,请告诉我:

val rdd1 = sc.textFile("some data")
rdd1.cache() //marks rdd1 as cached
val rdd2 = rdd1.filter(...)
val rdd3 = rdd1.map(...)
rdd2.saveAsTextFile("...")
rdd3.saveAsTextFile("...")

在上面,rdd1将仅从磁盘(例如HDFS)加载一次。 (当我保留rdd2时),然后从缓存中(假设有足够的RAM)保存rdd3时)

现在这是我的问题。假设我想缓存rdd2和rdd3,因为它们将在以后使用,但在创建后我不需要rdd1。

基本上有重复,不是吗?因为一旦计算出rdd2和rdd3,我就不再需要rdd1了,我应该可以解决它,对吧?问题是什么时候?

这会有效吗? (选项A)

val rdd1 = sc.textFile("some data")
rdd1.cache()   // marks rdd as cached
val rdd2 = rdd1.filter(...)
val rdd3 = rdd1.map(...)
rdd2.cache()
rdd3.cache()
rdd1.unpersist()

spark是否会向DAG添加unpersist调用?还是立即完成?如果它立即完成,那么当我从rdd2和rdd3读取时,基本上rdd1将被非缓存,对吗?

我应该这样做(选项B)吗?

val rdd1 = sc.textFile("some data")
rdd1.cache()   // marks rdd as cached
val rdd2 = rdd1.filter(...)
val rdd3 = rdd1.map(...)

rdd2.cache()
rdd3.cache()

rdd2.saveAsTextFile("...")
rdd3.saveAsTextFile("...")

rdd1.unpersist()

所以问题是: 选项A是否足够好?即rdd1只会加载文件一次吗? 或者我需要选择B吗?

3 个答案:

答案 0 :(得分:23)

似乎需要选项B.原因与Spark如何执行persist / cache和unpersist有关。由于RDD转换仅构建DAG描述而不执行,因此在您调用unpersist时,在选项A中,您仍然只有作业描述而不是正在运行的执行。

这是相关的,因为cachepersist调用只是将RDD添加到RDD的Map中,这些RDD标记为在作业执行期间保持持久性。但是,unpersist直接告诉blockManager从存储中驱逐RDD并删除持久RDD映射中的引用。

persist function

unpersist function

所以你需要在Spark实际执行后调用unpersist并将RDD与块管理器一起存储。

RDD.persist方法的评论提示: rdd.persist

答案 1 :(得分:2)

在选项A中,您在调用操作时没有显示(调用保存)

val rdd1 = sc.textFile("some data")
rdd.cache() //marks rdd as cached
val rdd2 = rdd1.filter(...)
val rdd3 = rdd1.map(...)
rdd2.cache()
rdd3.cache()
rdd1.unpersist()
rdd2.saveAsTextFile("...")
rdd3.saveAsTextFile("...")

如果序列如上,则选项A应使用缓存版本的rdd1来计算rdd2和rdd 3

答案 2 :(得分:0)

选项B是一种小调整的最佳方法。利用较便宜的行动方法。在您的代码提到的方法中,saveAsTextFile是一个昂贵的操作,用count方法替换它。

这里的想法是从DAG中移除大rdd1,如果它与进一步计算无关(在创建rdd2和rdd3之后)

从代码

更新了方法
val rdd1 = sc.textFile("some data").cache()
val rdd2 = rdd1.filter(...).cache() 
val rdd3 = rdd1.map(...).cache()

rdd2.count
rdd3.count

rdd1.unpersist()