如果我没有足够的记忆,会有什么火花?

时间:2013-11-30 14:56:05

标签: apache-spark

我是Spark的新手,我发现文档说Spark会将数据加载到内存中,以使迭代算法更快。

但是,如果我有一个10GB的日志文件并且只有2GB的内存呢? Spark会一如既往地将日志文件加载到内存中吗?

3 个答案:

答案 0 :(得分:13)

我认为这个问题在Spark网站(https://spark.apache.org/faq.html)的FAQ面板中得到了很好的解答:

  • 如果我的数据集不适合内存会怎样? 通常,每个数据分区都很小并且适合内存,并且这些分区一次只能处理几个。对于不适合内存的非常大的分区,Spark的内置运算符对数据集执行外部操作。
  • 当缓存的数据集不适合内存时会发生什么? Spark可以将其溢出到磁盘,也可以在每次请求时重新计算不适合RAM的分区。默认情况下,它使用重新计算,但您可以将数据集的存储级别设置为MEMORY_AND_DISK以避免这种情况。

答案 1 :(得分:6)

这里的关键是注意 RDD分为partitions (请参阅本答案的结尾处),每个分区都是一组元素(可以是文本行或例如整数)。分区用于在不同的计算单元中并行化计算。

所以键不是文件是否太大而是分区是否。在这种情况下,在FAQ:“Spark的操作符将数据溢出到磁盘,如果它不适合内存,允许它在任何大小的数据上运行良好”。生成OOM的大型分区的问题已解决here

现在,即使分区可以适合内存,这样的内存也可以满了。在这种情况下,它驱逐内存中的另一个分区以适应新分区。驱逐可能意味着:

  1. 完全删除分区:在这种情况下,如果再次需要分区,则重新计算
  2. 分区在指定的存储级别中保留。每个RDD都可以“标记”为使用this存储级别进行缓存/保留,有关如何使用,请参阅this
  3. 内存管理很好地解释了here“Spark将LRU缓存中的分区存储在内存中。当缓存达到其大小限制时,它会从中删除条目(即分区)。当分区有“disk”属性(即你的持久性级别允许在磁盘上存储分区),它将被写入HDD并且它所消耗的内存将被释放,除非你要求它。当你请求它时,它将被读入内存如果没有足够的内存,其他一些来自缓存的旧条目将被驱逐。如果你的分区没有“磁盘”属性,驱逐只是意味着破坏缓存条目而不将其写入硬盘“

    初始文件/数据的分区方式取决于数据的格式和类型,以及用于创建RDD的函数,请参阅this。例如:

    • 如果您已经有一个集合(例如java中的列表),您可以使用parallelize()并指定分区数。集合中的元素将分组。
    • 如果在HDFS中使用外部文件:“Spark为文件的每个块创建一个分区(HDFS默认为128MB)”
    • 如果从本地文本文件中读取,则每一行(以新行“\ n”结束,结束字符可以更改,请参阅this)是一个元素,并且多行形成一个分区。

    最后,我建议您阅读this以获取更多信息,并决定如何选择分区数量(太多或太少?)。

答案 2 :(得分:0)

由于没有足够的可用内存,它不会加载完整的10G。根据我的经验,根据您使用数据的方式,其中三种将会发生:

如果您尝试缓存10GB:

  1. 你将得到一个OOME
  2. 将加载数据
  3. 如果您只是处理数据:

    1. 数据将被换入/换出内存
    2. 当然,这与您的代码和您正在应用的转换密切相关。