当中间输出不适合 Spark 中的 RAM 时会发生什么

What happens when the intermediate output does not fit in RAM in Spark

我刚开始学习Spark。根据我的理解,Spark 将中间输出存储在 RAM 中,因此与 Hadoop 相比非常快。如果我错了,请纠正我。

我的问题是,如果我的中间输出是 2 GB 而我的空闲 RAM 是 1 GB,那么在这种情况下会发生什么?这可能是一个愚蠢的问题,但我还没有理解 Spark 的内存概念。谁能给我解释一下 Spark 的内存概念?

谢谢

如果我理解正确你的问题,我可以回复如下:

中间临时存储目录由配置Spark上下文时的spark.local.dir配置参数指定。

spark.local.dir 目录用于 Spark 中的 "scratch" space,包括映射输出文件和存储在磁盘上的 RDD。 [Ref. Spark Configuration.]

这应该在您系统的快速本地磁盘上。它也可以是不同磁盘上多个目录的逗号分隔列表。

不过,您在这里解决的问题也称为 RDD 持久性。在使用 Spark 缓存你应该已经知道的基础知识中,还有所谓的 RDD 的存储级别,它允许不同的存储级别。

例如,这将允许您将数据集保存在磁盘上将其保存在内存中,但作为序列化的Java对象(为了保存 space),跨节点复制它,或者将它存储在堆外 Tachyon (最后一个是实验性的)More information here.

注意: 这些级别是通过将 StorageLevel 对象(Scala、Java、Python)传递给 persist 来设置的。 cache 方法是一个 shorthand 用于使用默认存储级别,即 StorageLevel.MEMORY_ONLY Spark 在内存中存储反序列化的对象。

所以现在回答你的问题,

如果我的中间输出是 2 GB 而我的空闲 RAM 是 1 GB,那么在这种情况下会发生什么?

我说这取决于您如何配置和调整您的 Spark(应用程序、集群)。

注意: Spark中的内存在概念上类似于世界上任何内存系统,主要目的是避免沉重和昂贵IOs.这也意味着,如果我回到你的问题,如果你决定坚持使用 DISK,那么你将失去性能。在答案中引用的官方文档中有更多相关信息。

这个问题问的是 Spark 中的 RDD persistence

You can mark an RDD to be persisted using the persist() or cache() methods on it. The first time it is computed in an action, it will be kept in memory on the nodes. Spark’s cache is fault-tolerant – if any partition of an RDD is lost, it will automatically be recomputed using the transformations that originally created it.

根据您为 RDD 设置存储级别的方式,可以配置不同的结果。例如,如果您将存储级别设置为 MEMORY_ONLY(这是默认存储级别),您的输出将尽可能多地存储在内存中,并即时重新计算 RDD 的其余部分。您可以像下面这样保留您的 RDD 并应用您的存储级别:rdd.persist(MEMORY_ONLY)

在您的示例中,将计算 1GB 的输出并将其保存在内存中,另外 1GB 将在需要时计算以供后续步骤使用。根据您的用例,还可以设置其他存储级别:

  1. MEMORY_AND_DISK -- 计算整个 RDD,但必要时将一些内容溢出到磁盘
  2. MEMORY_ONLY_SER, MEMORY_AND_DISK_SER -- 与上面相同,但所有元素都被序列化
  3. DISK_ONLY -- 将所有分区直接存储到磁盘
  4. MEMORY_ONLY_2, MEMORY_AND_DISK_2 -- 与上面相同,但分区被复制两次以获得更大的容忍度

同样,您必须查看您的用例以确定最佳存储级别。在某些情况下,RDD 的重新计算实际上可能比从磁盘加载所有内容更快。在其他情况下,快速序列化程序可以减少从磁盘中获取的数据,从而快速响应有问题的数据。