繁体   English   中英

执行程序上的Spark对象(单例)序列化

[英]Spark Object (singleton) serialization on executors

我不确定我想要实现的目标是否可行。 我所知道的是,我正在从执行程序访问单例对象,以确保其构造函数在每个执行程序上仅被调用一次。 这种模式已经得到证明,并且可以在我的代码库中的类似用例中正常使用。

但是,我想知道的是,是否可以在驱动程序上将对象初始化后再运送对象。 在这种情况下,当访问ExecutorAccessedObject.y ,理想情况下,它不会调用println而是仅返回值。 这是一个高度简化的版本,实际上,我想在驱动程序上调用某些外部系统,因此在执行程序上访问时,它不会重新调用该外部系统。 我对@transient lazy val x可以在执行程序上重新初始化一次没问题,因为它将保存一个无法序列化的连接池。

object ExecutorAccessedObject extends Serializable {
  @transient lazy val x: Int = {
    println("Ok with initialzing this on the executor. I.E. database connection pool")
    1
  }

  val y: Int = {
    // call some external system to return a value.
    // I do not want to call the external system from the executor
    println(
      """
        |Idealy, this would not be printed on the executor.
        |return value 1 without re initializing
      """)
    1
  }
  println("The constructor will be initialized Once on each executor")
}


someRdd.mapPartitions { part =>
  ExecutorAccessedObject
  ExecutorAccessedObject.x // first time accessed should re-evaluate
  ExecutorAccessedObject.y // idealy, never re-evaluate and return 1
  part
}

我也尝试使用广播变量来解决这个问题,但是我不确定如何在单例对象中访问广播变量。

我想知道的是,在驱动程序上初始化对象之后,是否可以运送该对象。

你不能。 作为单例的Objects永远不会交付给执行者。 每当首次访问对象时,都会在本地进行初始化。

如果调用的结果是可序列化的,则只需将其单独传递,要么作为参数传递给ExecutorAccessedObject (隐式或显式),要么使ExecutorAccessedObject可变(并添加所需的同步)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM