我们假设我有一个Tb数据文件。 十个节点集群中的每个节点内存为3GB。
我想使用spark处理文件。 但One TeraByte如何适应记忆?
会丢失内存异常吗?
它是如何运作的?
答案 0 :(得分:6)
正如Thilo所提到的,Spark不需要在内存中加载所有内容以便能够处理它。这是因为Spark会将数据划分为更小的块并分别对这些块进行操作。分区的数量,以及它们的大小取决于几个方面:
FileSystem
定义的,用于读取文件并应用于其他文件系统的文件,Spark使用Hadoop来处理这些文件。repartition(N)
或coalesce(N)
来更改分区数量,从而更改其大小。 coalesce
首选是为了减少数量而不是在节点之间移动数据,而repartition
则允许您指定一种新的方式来分割数据,即更好地控制数据的哪些部分被处理同一个节点。spark.sql.shuffle.partitions
(默认设置为200)确定由联接和聚合产生的DataFrame
分区数前面的内容与Spark中的数据标准处理有关,但是我觉得你可能会因为Spark被称为'内存中'而错过了想法,所以我想解决这个问题。默认情况下,Spark中没有任何内容比任何其他数据处理工具更“内存”:一个简单的示例sc.textFile(foo).map(mapFunc).saveTextFile(bar)
读取文件(逐块并分布在您的节点上),内存中的映射是否正确(像任何计算机程序一样)然后再将其保存到存储中。 Spark对内存的使用在下面变得更加有趣(在Scala中,因为我对它更熟悉,但在Python中概念和方法名称完全相同):
val rdd = sc.textFile(foo)
// Do some preprocessing, such as parsing lines
val preprocessed = rdd.map(preprocessFunc)
// Tell Spark to cache preprocessed data (by default in memory)
preprocessed.cache()
// Perform some mapping and save output
preprocessed.map(mapFunc1).saveTextFile(outFile1)
// Perform a different mapping and save somewhere else
preprocessed.map(mapFunc2).saveTextFile(outFile2)
这里的想法是使用cache()
,因此预处理不必两次(可能);默认情况下,Spark不保存任何中间结果,但计算每个单独操作的完整链,其中“操作”是saveTextFile
调用。
我说'可能',因为实际缓存数据的能力受到节点内存的限制。 Spark为缓存存储保留了一定的内存,与工作内存分开(参见http://spark.apache.org/docs/latest/configuration.html#memory-management如何管理这些内存部分的大小),并且只能缓存最多可以容纳的数量。
根据您的分区,它可能会更少。假设您的3个节点中每个节点都有2GB的存储空间,preprocessed
中的数据为6GB。如果此数据有3个分区,则它将完全适合,并且将从内存加载到mapFunc2
的所有输入数据。但是如果你说有4个分区,每个1.5Gb,每个节点只能缓存1个分区;第四个分区将不适合仍然留在每台机器上的0.5GB,因此必须重新计算第二个映射的分区,并且只有3/4的预处理数据将从内存中读取。
所以在这个意义上,最好有许多小分区,以尽可能提高缓存效率,但这可能还有其他方面的缺点:如果你碰巧使用具有细粒度模式的Mesos,以及大量的小的输出文件(如果在保存之前没有合并),因为Spark将每个分区保存为单独的文件。
正如杜尔加所说,也有可能将不适合内存泄漏的数据泄露到磁盘上,你可以按照他的链接:)
答案 1 :(得分:1)
默认情况下,存储级别为 MEMORY_ONLY ,它会尝试将数据放入内存中。如果数据无法容纳在内存中,它将因内存不足而失败。
它支持其他存储级别,例如MEMORY_AND_DISK,DISK_ONLY等。您可以通过Spark documentation了解不同的存储级别。您可以在RDD上调用persist函数以使用不同的存储级别。