我为什么要明确告诉Spark哪些数据需要缓存?

9
在Spark中,每次对RDD执行任何操作时,都会重新计算RDD。因此,如果我们知道RDD将要被重用,我们应该显式地缓存RDD。
假设Spark决定懒惰地缓存所有的RDD,并使用LRU自动将最相关的RDD保留在内存中(这是大多数缓存工作方式)。这将对开发人员非常有帮助,因为他不必考虑缓存并集中精力于应用程序。我也看不出它如何对性能产生负面影响,因为很难跟踪程序内变量(RDD)被使用的次数,大多数程序员将决定缓存大多数RDD。
缓存通常是自动发生的。以操作系统/平台、框架或工具为例。但是由于分布式计算中缓存的复杂性,我可能会忽略为什么缓存不能自动进行或性能影响。
因此,我不明白为什么我必须显式地缓存,因为:
1.它看起来不美观
2.很容易被忽视
3.很容易过度/欠度使用
1个回答

19

一些主观原因:

  • 实际上,缓存很少需要使用,仅对于迭代算法、打破长的血统有用。例如,典型的ETL管道可能根本不需要缓存。对大多数RDD进行缓存绝对不是正确的选择。
  • 没有通用的缓存策略。实际选择取决于可用资源,如内存量、磁盘(本地、远程、存储服务)、文件系统(内存中、磁盘上)和特定应用。
  • 在磁盘上持久化很昂贵,内存中持久化会给JVM带来更大的压力,并占用Spark中最宝贵的资源。
  • 没有自动缓存而不做出关于应用语义的假设是不可能的。特别是:

    • 数据源变化时的预期行为。没有通用答案,在许多情况下,无法自动跟踪更改。
    • 区分确定性和非确定性变换,并选择缓存和重新计算之间的差异
  • 将Spark缓存与操作系统级缓存进行比较是没有意义的。操作系统缓存的主要目标是减少延迟。在Spark中,延迟通常不是最重要的因素,缓存用于其他目的,如一致性、正确性和减少系统不同部分的压力。
  • 如果缓存不使用堆外存储,则缓存会给垃圾收集器带来额外的压力。实际上,GC成本可能比重新计算数据的成本更高。
  • 根据数据和缓存方法,从缓存中读取数据在占用内存方面可能显着不够高效。
  • 缓存会干扰Spark SQL中可用的更高级优化,有效地禁用了分区修剪或谓词和投影下推。

值得注意的是:

  • LRU自动处理删除缓存数据
  • 一些数据(例如中间洗牌数据)会自动持久化。我承认这使得前面的一些论点至少部分无效。
  • Spark缓存不会影响系统级别或JVM级别机制

我不同意“很少需要缓存”的理由。到目前为止,无论是操作系统还是像文件读取这样的API都会处理缓存,因此我们不必担心它。但对于任何非平凡应用程序,缓存几乎总是必需的。 - rakesh
并不完全是这样。尤其是对于基于磁盘的存储而言,重新计算可能比缓存更为经济。 - zero323
那不是真的,@rakesh!在这些情况下并非强制要求。本答案讨论的原因是完全有效的。请记住,Spark不是内存数据存储或缓存系统。 - eliasah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接