【问题标题】:Spark local variable broadcast to executorSpark局部变量广播到执行器
【发布时间】:2020-01-19 22:09:02
【问题描述】:
var countryMap = Map("Amy" -> "Canada", "Sam" -> "US", "Bob" -> "Canada")
val names = List("Amy", "Sam", "Eric")
sc.parallelize(names).flatMap(broadcastMap.value.get).collect.foreach(println)

//output
Canada
US

我在 YARN 模式下运行这个 spark 作业,我确信驱动程序和执行程序不在同一个节点/JVM 中(参见附图)。由于 countryMap 不是广播变量,因此执行程序不应该看到它,并且此代码不应该打印任何内容。但是,它打印了CanadaUS

我的问题是,如果局部变量是可序列化的,Spark 是否会自动将局部变量填充到执行程序?如果不是,executor如何查看驱动的局部变量?

【问题讨论】:

    标签: scala apache-spark distributed broadcast


    【解决方案1】:

    海伊·爱德华兹,

    当您调用将结果集返回给驱动程序的collect 时,请尝试执行映射。你可以找到映射的原因是生成的。

    干杯,

    【讨论】:

    • 我认为这不是真的。 Collect 会将所有执行程序的数据提取到驱动程序。映射部分仍然单独发生在每个执行器中。请看我的回答。 Spark其实会自动广播局部变量
    【解决方案2】:

    局部变量:驱动程序和每个执行程序,不需要序列化,在执行器/驱动程序内共享。 主要变量:驱动和任务的每个副本(绝缘),需要序列化

    【讨论】:

      【解决方案3】:

      Spark 动作通过一组阶段执行,由分布式“shuffle”操作分隔。 Spark 自动广播每个阶段中的任务所需的公共数据。以这种方式广播的数据以序列化形式缓存,并在运行每个任务之前进行反序列化。这意味着显式创建广播变量仅在跨多个阶段的任务需要相同数据或以反序列化形式缓存数据很重要时才有用。

      参考https://spark.apache.org/docs/2.3.0/rdd-programming-guide.html#broadcast-variables

      基本上,驱动程序中的局部变量会自动广播给执行程序。但是,当您需要跨不同阶段的广播变量时​​,您需要创建它们。

      【讨论】:

      【解决方案4】:

      要让broadcastMap.value.get 函数在集群上运行,Spark 需要序列化broadcastMap 并发送到每个执行程序,因此您拥有一个函数,其中已经以对象实例的形式附加了数据。如果您使 broadcastMap 类不可序列化 - 您将无法运行此代码。

      因此,Spark 不会向执行程序填充局部变量,而是您明确告诉它序列化对象 broadcastMap 并分布式运行该对象的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-18
        • 1970-01-01
        • 1970-01-01
        • 2016-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多