簡體   English   中英

Spark執行器上的對象緩存

[英]Object cache on Spark executors

Spark專家的一個好問題。

我正在處理map操作(RDD)中的數據。 在mapper函數中,我需要查找類A對象以用於處理RDD中的元素。

由於這將在執行程序上執行,並且類型A的元素(將被查找)的創建恰好是一項昂貴的操作,我想在每個執行程序上預加載和緩存這些對象。 這樣做的最佳方式是什么?

  • 一個想法是廣播查找表,但A類不可序列化(無法控制其實現)。

  • 另一個想法是將它們加載到單個對象中。 但是,我想控制加載到查找表中的內容(例如,可能在不同的Spark作業上有不同的數據)。

理想情況下,我想指定將在執行程序上加載一次(包括Streaming的情況,以便查找表在批處理之間保留在內存中),通過在啟動期間驅動程序上可用的參數,數據得到處理。

是否有干凈優雅的方式或無法實現?

這正是broadcast.的目標用例broadcast. 廣播變量傳輸一次並使用種子有效地移動到所有執行器,並保留在內存/本地磁盤中,直到您不再需要它們為止。

在使用其他人的界面時,序列化經常會成為一個問題。 如果您可以強制執行您使用的對象是可序列化的,那么這將是最佳解決方案。 如果這是不可能的,那么你的生活會變得更加復雜。 如果無法序列​​化A對象,則必須在每個任務的執行程序上創建它們。 如果它們存儲在某個文件中,則看起來像:

rdd.mapPartitions { it => 
  val lookupTable = loadLookupTable(path)
  it.map(elem => fn(lookupTable, elem))
}

請注意,如果您正在使用此模型,則必須為每個任務加載一次查找表 - 您無法從廣播變量的跨任務持久性中受益。

編輯:這是另一個模型,我相信讓你可以跨每個JVM的任務共享查找表。

class BroadcastableLookupTable {
  @transient val lookupTable: LookupTable[A] = null

  def get: LookupTable[A] = {
    if (lookupTable == null)
      lookupTable = < load lookup table from disk>
    lookupTable
  }
}

這個類可以廣播(沒有實質性的傳輸),並且第一次按JVM調用它,你將加載查找表並返回它。

如果序列化變得不可能,那么如何將查找對象存儲在數據庫中? 它不是最簡單的解決方案,但應該可以正常工作。 我可以建議檢查例如spark-redis ,但我相信那里有更好的解決方案。

由於A不可序列化,因此最簡單的解決方案是創建自己的可序列化類型A1其中包含計算所需的所有A數據。 然后在廣播中使用新的查找表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM