当我运行以下代码时:
val newRDD = prevRDD.map(a => (a._1, 1L)).distinct.persist(StorageLevel.MEMORY_AND_DISK_SER)
newRDD.checkpoint
print(newRDD.count())
并观察Yarn中的各个阶段,我注意到Spark正在进行DAG计算TWICE - 一次用于实现RDD并将其缓存的distinct + count,然后是完全SECOND时间来创建检查点复制。
由于RDD已经实现并缓存,为什么检查点不能简单地利用这一点,并将缓存的分区保存到磁盘?
是否存在一种现有方式(某种配置设置或代码更改)以强制Spark利用此功能并仅运行ONCE操作,并且检查点只会复制内容?
我需要两次“实现”吗?
val newRDD = prevRDD.map(a => (a._1, 1L)).distinct.persist(StorageLevel.MEMORY_AND_DISK_SER)
print(newRDD.count())
newRDD.checkpoint
print(newRDD.count())
我创建了一个Apache Spark Jira票证,以使其成为功能请求: https://issues.apache.org/jira/browse/SPARK-8666
答案 0 :(得分:6)
看起来这可能是一个已知问题。查看较旧的JIRA票证https://issues.apache.org/jira/browse/SPARK-8582
答案 1 :(得分:1)
这是一个古老的问题。但是它也影响了我,所以我做了一些挖掘。在jira和github的更改跟踪历史记录中,我发现了一堆非常无用的搜索结果。这些搜索结果包含了开发人员对他们提出的编程更改的许多技术ba语。最终,这对我没有多大帮助,我建议您限制花在看它上的时间。
关于此事,我能找到的最明确的信息是: https://github.com/JerryLead/SparkInternals/blob/master/markdown/english/6-CacheAndCheckpoint.md
需要检查的RDD将被计算两次;因此建议在rdd.checkpoint()之前先做rdd.cache()
鉴于OP实际上确实使用了持久性和检查点,因此他可能走在正确的轨道上。我怀疑唯一的问题在于他调用检查点的方式。我很新,但我认为他应该这样做:
newRDD = newRDD.checkpoint
希望这很清楚。根据我的测试,这消除了我的一个数据帧的冗余计算。
答案 2 :(得分:0)
由于缺少内存,您缓存的数据可能会被驱逐,您可以打开Spark UI来检查其是否正确。