我刚开始学习Spark
。根据我的理解,Spark
将中间输出存储在RAM中,因此与Hadoop
相比非常快。如果我错了,请纠正我。
我的问题是,如果我的中间输出是2 GB而我的空闲RAM是1 GB,那么在这种情况下会发生什么?这可能是一个愚蠢的问题,但我还没有理解Spark的内存概念。任何人都可以向我解释一下Spark的内存概念吗?
由于
答案 0 :(得分:6)
这个问题是在Spark中询问RDD persistence。
您可以使用persist()或cache()方法标记要保留的RDD。第一次在动作中计算它,它将保留在节点的内存中。 Spark的缓存是容错的 - 如果丢失了RDD的任何分区,它将使用最初创建它的转换自动重新计算。
根据您为RDD设置存储级别的方式,可以配置不同的结果。例如,如果将存储级别设置为MEMORY_ONLY
(这是默认存储级别),则输出将尽可能多地存储在内存中,并在运行时重新计算其余的RDD。您可以保留RDD并应用以下存储级别:rdd.persist(MEMORY_ONLY)
。
在您的示例中,将计算1GB的输出并在内存中,并在将来步骤需要时计算另一个1GB。根据您的使用情况,还可以设置其他存储级别:
MEMORY_AND_DISK
- 计算整个RDD,但在必要时将一些内容泄露到磁盘MEMORY_ONLY_SER
,MEMORY_AND_DISK_SER
- 与上述相同,但所有元素都已序列化DISK_ONLY
- 将所有分区直接存储到磁盘MEMORY_ONLY_2
,MEMORY_AND_DISK_2
- 与上述相同,但分区会被复制两次以获得更大的容忍度同样,您必须查看您的用例以确定最佳存储级别。在某些情况下,重新计算RDD实际上可能比从磁盘加载所有内容更快。在其他情况下,快速序列化程序可以减少从磁盘中获取的数据,从而快速响应所讨论的数据。
答案 1 :(得分:2)
如果我理解你的问题,我可以回复以下内容:
配置Spark上下文时,{em>中间或临时存储目录由spark.local.dir
配置参数指定。
spark.local.dir
目录用于Spark中的“临时”空间,包括映射输出文件和存储在磁盘上的RDD。 [Ref. Spark Configuration.]
这应该位于系统中快速的本地磁盘上。它也可以是不同磁盘上多个目录的逗号分隔列表。
然而,您在此处解决的问题也称为RDD持久性。在您应该已经知道使用Spark缓存的基础知识中,还有一种称为RDD的存储级别,它允许不同的存储级别。
例如,这将允许您将数据集保留在磁盘上,将其保留在内存中但作为序列化Java对象(以节省空间),跨节点复制它,或者将它存储在Tachyon的堆外 (最后一个是实验性的)。 More information here
注意:通过将StorageLevel对象(Scala,Java,Python)传递给persist
来设置这些级别。 cache
方法是使用默认存储级别的简写,即StorageLevel.MEMORY_ONLY
,其中Spark将反序列化的对象存储在内存中。
现在回答你的问题,
如果我的中间输出为2 GB且我的可用内存为1 GB,那么在这种情况下会发生什么?
我说这取决于你如何配置和调整你的Spark(app,cluster)。
注意: Spark中的内存类似于世界上任何内存系统的概念,主要目的是避免繁重且昂贵的IO。这也意味着,如果我回到你的问题,如果你决定坚持DISK每说,你将失去性能。更多内容在答案中引用的官方文档中。