当文件大小超出Spark主存储器容量时,Spark如何读取大型文件(PB级别)?

39

在这些情况下,大文件会发生什么?

1) Spark从NameNode获取数据的位置。如果数据大小超过了NameNode提供的信息,那么Spark会在此时停止吗?

2) Spark根据数据节点块大小对数据进行分区,但是所有数据无法存储到主内存中。 在这里,我们不使用StorageLevel。 那么这里会发生什么?

3) Spark对数据进行分区,一些数据将存储在主内存中,一旦这些主内存存储的数据处理完成,Spark会从磁盘加载其他数据。


3
Spark对于大数据文件的处理取决于读取数据后你要做什么。如果使用cache方法会导致内存溢出(OOM),但如果只进行一系列操作,当内存填满时Spark将自动溢写到磁盘。如果集群中的磁盘放不下所有数据,工作节点上的操作系统通常会终止进程,此时需要增加磁盘(或内存)容量来完成作业。 - Glennie Helles Sindholt
{btsdaf} - Arpit Rai
2个回答

101
首先,Spark只有在调用动作(例如countcollectwrite)时才开始读入数据。一旦调用了操作,Spark就会将数据加载到分区中 - 同时加载的分区数量取决于可用核心数。因此,在Spark中,您可以认为1个分区=1个核心=1个任务。请注意,所有同时加载的分区都必须适合内存,否则将出现OOM。
假设您有几个阶段,Spark然后仅在已加载的分区上运行第一个阶段的转换。一旦它在已加载的分区上应用了数据变换,它将其输出存储为洗牌数据,然后读入更多分区。然后,它在这些分区上应用转换,将输出存储为洗牌数据,读入更多分区,直到读取所有数据为止。
如果您不应用任何转换,而只是执行例如count,则Spark仍会按分区读入数据,但不会将任何数据存储在集群中,如果再次执行count,则会再次读取所有数据。为避免多次读取数据,您可以调用cachepersist>,在这种情况下,Spark将试图将数据存储在集群中。对于cache(与persist(StorageLevel.MEMORY_ONLY)相同),它将所有分区存储在内存中 - 如果内存不足,您将会遇到OOM。如果调用persist(StorageLevel.MEMORY_AND_DISK),它将尽可能多地存储在内存中,其余数据将被放置在磁盘上。如果数据也不适合磁盘,则操作系统通常会杀死您的工作程序。
请注意,Spark有自己的小型内存管理系统。您分配给Spark作业的一些内存用于保存正在处理的数据,另一些内存用于存储如果调用cachepersist时。希望这个解释能够帮助您 :)

1
对于大型数据集,设置StorageLevel.MEMORY_AND_DISK是唯一的选择吗? - vijayraj34
1
如果您的数据集超过了内存的容量,那么您既不能使用cache,也不能使用persist(StorageLevel.MEMORY_ONLY)。但是您可以使用其他所有的存储级别,所以StorageLevel.DISK_ONLY也是一个选择 :) - Glennie Helles Sindholt
3
@devesh 使用StorageLevel.DISK_ONLY肯定会影响性能!我之所以提到它,是因为问题是关于StorageLevel.MEMORY_AND_DISK是否是_唯一_选项,而实际上不是 :) - Glennie Helles Sindholt
1
你可以通过 --executor-memory 标志(与 spark.executor.memoryOverhead 设置相结合)配置每个执行器的内存。分配给并发加载任务的内存的实际分布由 Spark 内部管理,但你可能可以假设大致均匀分布。 - Glennie Helles Sindholt
1
无论如何,如果所有数据无法适应RDD,则Spark将尝试重新计算。根据文档,这至少是最新的行为 - MEMORY_ONLY将RDD存储为JVM中反序列化的Java对象。如果RDD不适合内存,则某些分区将不会被缓存,并且每次需要时都会动态地重新计算。这是默认级别。 - Nag
显示剩余7条评论

11
这里是引用自Apache Spark FAQ(FAQ | Apache Spark)的原话:

我的数据需要放入内存才能使用Spark吗?

不需要。如果数据无法放入内存,则Spark运算符会将其溢出到磁盘上,从而使它能够在任何大小的数据上高效运行。同样,如果缓存数据集无法放入内存,则根据RDD的存储级别,在需要时可以将其溢出到磁盘上或重新计算。

在Apache Spark中,如果数据无法放入内存,则Spark会将该数据简单地保存到磁盘中。

Apache Spark中的persist方法提供了六种持久化存储级别来持久化数据。

MEMORY_ONLY, MEMORY_AND_DISK, MEMORY_ONLY_SER 
(Java and Scala), MEMORY_AND_DISK_SER 
(Java and Scala), DISK_ONLY, MEMORY_ONLY_2, MEMORY_AND_DISK_2, OFF_HEAP.

OFF_HEAP 存储正在进行试验。

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