在 Spark 中,是不是可以在两个 executor 之间共享数据?

Posted

技术标签:

【中文标题】在 Spark 中,是不是可以在两个 executor 之间共享数据?【英文标题】:In Spark, is it possible to share data between two executors?在 Spark 中,是否可以在两个 executor 之间共享数据? 【发布时间】:2016-10-22 09:57:37 【问题描述】:

我有一个非常大的只读数据,我希望同一节点上的所有执行程序都使用它。在 Spark 中这可能吗?我知道,你可以广播变量,但你能广播非常大的数组吗?在幕后,它是否在同一节点上的执行程序之间共享数据?这如何能够在同一节点上运行的 executor 的 JVM 之间共享数据?

【问题讨论】:

数据是如何固定到执行器的?您能描述一下您要解决的问题吗? 基本上,我有一个大约 6 GB 的只读数据。每个执行程序必须不时读取此数据,因为它是一种查找表。每个执行者都必须有权访问整个查找表。我不想给每个执行者那么多内存。我希望在同一节点上运行的执行程序之间共享内存,这样我就可以通过为每个执行程序分配少量内存来摆脱困境。 听起来你可以使用一些本地服务来做到这一点。例如。将该数据加载到本地 Redis(或类似的内存数据库/缓存)中,并使用 Spark 作业中的单例 JVM 对象来寻址本地实例。您还需要一个执行刷新的管理服务。我认为没有开箱即用的 Spark 解决方案可以实现您想要的。 广播变量呢。它们是如何工作的?它们不是也在同一个节点上的 executor 之间共享吗? 广播变量允许在同一个执行器VM上运行的任务之间共享数据,因此每个执行器只需加载一次数据。 【参考方案1】:

是的,当考虑到您的数据是只读的(不可变的)时,您可以使用 broadcast 变量。广播变量必须满足以下属性。

适合记忆 不可变 分布式到集群

因此,这里唯一的条件是您的数据必须能够放入一个节点的内存中。这意味着数据不应该是超大或超出内存限制的任何东西,比如一张大表。

每个执行器都会收到广播变量的副本,并且该特定执行器中的所有任务都在读取/使用该数据。这就像向集群中的所有工作节点发送大量的只读数据。 即,只向每个工作人员发送一次,而不是每个任务和执行程序(它的任务)读取数据。

【讨论】:

@pythonic 询问如何“在 JVM 之间共享数据”。 @LostInOverflow 我相信这个问题会造成一些混乱。 OP 没有使用正确的措辞。 2 个执行器!= 2 个应用程序 JVM 好的,是的。 JVM 分享的答案是,Apache Spark 是一个分布式数据处理框架。因此,在这里您不能共享作业/应用程序/任务或 RDD。数据共享的唯一方法是通过像 HDFS 这样的持久存储。 Apache Ignite,一个在 RDD 之上提供抽象的框架,称为 IgniteRDD,它是原生 Spark RDD 和 DataFrame API 的实现,它在其他作业、应用程序和工作人员之间共享 RDD 的状态。 @eliasah 我想你的意思是 2 个执行线程!= 2 个应用程序 JVM? 如前所述,我们无法在执行器之间共享数据,并且执行器运行在不同的 JVM 上。 2 个执行器线程始终在同一个 JVM 上运行一个应用程序。【参考方案2】:

我假设您问执行者如何共享可变状态。如果您只需要共享不可变数据,那么您可以参考@Stanislav 的答案。 如果你需要执行者之间的可变状态,有很多方法:

    共享外部 FS/DB 有状态流databricks doc 可变分布式共享缓存Ignite RDD

【讨论】:

以上是关于在 Spark 中,是不是可以在两个 executor 之间共享数据?的主要内容,如果未能解决你的问题,请参考以下文章

pyspark 中 spark.sql() 和 cursor.execute 的区别?

深入浅出Spark啥是Standalone

技术猩球王玉明:Spark Adaptive Execution 帮助 eBay 解决的重要问题

Could not locate executable nullinwinutils.exe in the Hadoop binaries解决方式 spark运行wordcoult

Spark调优 | Spark OOM问题常见解决方式

Adaptive Execution如何让Spark SQL更高效更好用