8

当spark通过驱动程序提取数据时,我试图简单地说,然后当spark不需要通过驱动程序提取数据时。

我有3个问题-

  1. 假设您有一个存储在 HDFS 中的 20 TB 平面文件文件,并从驱动程序中使用相应库的开箱即用功能之一(sc.textfile(path)sc.textfile(path).toDF等)将其拉入数据帧或 RDD。如果驱动程序仅使用 32 GB 内存运行,是否会导致驱动程序出现 OOM?或者至少有司机吉姆的交换?或者 spark 和 hadoop 是否足够聪明,可以将来自 HDFS 的数据分发到 spark 执行器中,从而在不通过驱动程序的情况下生成数据帧/RDD?
  2. 除了来自外部 RDBMS 之外,与 1 完全相同的问题?
  3. 与 1 完全相同的问题,除了来自特定节点文件系统(只是 Unix 文件系统,20 TB 文件但不是 HDFS)?
4

1 回答 1

5

关于1

Spark 使用分布式数据结构,如 RDD 和 Dataset(以及 2.0 之前的 Dataframe)。以下是您应该了解的有关此数据结构的事实,以回答您的问题:

  1. 所有的转换操作,如(映射、过滤器等)都是惰性的。这意味着除非您需要操作的具体结果(如减少、折叠或将结果保存到某个文件),否则不会执行读取。
  2. 在 HDFS 上处理文件时,Spark 使用文件分区进行操作。分区是可以处理的最小逻辑批数据。通常一个分区等于一个 HDFS 块,并且分区的总数永远不能少于一个文件中的块数。常见的(和默认的)HDFS 块大小为 128Mb
  3. RDD 和 Dataset 中的所有实际计算(包括从 HDFS 读取)都在 executors 内部执行,而不是在驱动程序上执行。Driver 创建 DAG 和逻辑执行计划,并将任务分配给 executor 以进行进一步处理。
  4. 每个执行程序针对特定的数据分区运行先前分配的任务。因此,通常如果您只为执行程序分配一个核心,它会同时处理不超过 128Mb(默认 HDFS 块大小)的数据。

所以基本上当你调用时sc.textFile没有实际的阅读发生。所有提到的事实都解释了为什么在处理 20 Tb 的数据时也不会发生 OOM。

有一些特殊情况,例如 iejoin操作。但即使在这种情况下,所有执行程序都会将它们的中间结果刷新到本地磁盘以进行进一步处理。

关于2

在 JDBC 的情况下,您可以决定您的表有多少个分区。并在表中选择适当的分区键,将数据正确拆分为分区。由您决定同时将多少数据加载到内存中。

关于3

本地文件的块大小由fs.local.block.size属性控制(我猜默认为 32Mb)。因此它与 1(HDFS 文件)基本相同,只是您将从一台机器和一个物理磁盘驱动器读取所有数据(这在 20TB 文件的情况下效率极低)。

于 2016-08-22T21:56:57.983 回答