簡體   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