2017-05-04 45 views
3

我使用LongAccumulator作爲地圖操作中的共享計數器。但似乎我沒有正確使用它,因爲工作節點上的計數器狀態未更新。下面是我的櫃檯類的樣子:工作節點爲什麼沒有看到另一個工作節點上的累加器更新?

public class Counter implements Serializable { 

    private LongAccumulator counter; 

    public Long increment() { 
     log.info("Incrementing counter with id: " + counter.id() + " on thread: " + Thread.currentThread().getName()); 
     counter.add(1); 
     Long value = counter.value(); 
     log.info("Counter's value with id: " + counter.id() + " is: " + value + " on thread: " + Thread.currentThread().getName()); 
     return value; 
    } 

    public Counter(JavaSparkContext javaSparkContext) { 
     counter = javaSparkContext.sc().longAccumulator(); 
    } 
} 

至於當應用程序在多個工作節點中運行的我能理解的文檔這應該正常工作:

蓄電池是變量,這些變量只有「添加「到通過關聯和交換操作,因此可以有效地支持並行。它們可以用來實現計數器(如在MapReduce中)或者和。 Spark本身支持數字類型的累加器,程序員可以添加對新類型的支持。

但這裏是在計數器上的2名不同的工人增加的結果,因爲它看起來像的狀態不是節點之間共享:

信息計數器:id爲遞增計數器:866上線程:執行程序任務啓動worker-6 INFO計數器:計數器的值爲:866爲:線程上的1:執行程序任務啓動worker-6
INFO計數器:在線程上遞增計數器:id:866執行程序任務啓動worker-0 INFO計數器:ID爲866的計數器值爲:1在線程上:執行程序任務啓動worker-0

我理解累加器構想錯誤還是有任何設置我必須開始執行任務?

回答

2

shouldn't work:一個集羣上運行

任務可以使用add方法,然後添加到它。但是,它們無法讀取其價值。只有驅動程序可以使用其值方法讀取累加器的值。

每個任務都有自己的累加器,它在本地更新,並在驅動程序上與「共享」副本合併,一旦任務完成並且結果已被報告。

Accumulator API(現在的包裝AccumulatorV2)使用value從任務中的時候,居然拋出一個異常,但由於某種原因它在AccumulatorV2省略。

你體驗什麼是真正相似,這裏How to print accumulator variable from within task (seem to "work" without calling value method)?

-1

描述從the answer from @user6910411(重點煤礦)舊行爲:

每個任務都有它自己的蓄電池,其在本地更新,並合併withing在驅動程序上「共享」複製,一旦任務完成並且結果已被報告

粗體答案的部分不是100%正確的。

將內部和外部累加器的當前值發送給驅動程序,每個執行程序心跳必須定期發生,或者驅動程序假定執行程序丟失。

定期間隔由spark.executor.heartbeatInterval屬性控制,默認爲10s

每個執行器的心跳與驅動程序之間的時間間隔。心跳讓司機知道執行者仍然活着,並使用用於正在進行的任務的指標對其進行更新。 spark.executor.heartbeatInterval應該明顯小於spark.network.timeout

如上所述,心跳是「傳輸層」以將部分更新傳遞給累加器(在執行器上)給驅動器。

有兩種累加器 - 內部和非內部(缺乏更多的專有名稱,我將稱其爲非內部累加器)。

內部蓄電池用於火花用來讓管理員/操作員知道幕後發生了什麼任務指標。

同樣的機制星火採用局部更新發送到非內部蓄電池所以當地的更新,給蓄電池(在其中任務運行執行人)是駕駛員遺囑執行人心跳可見。

我對此不太確定,但駕駛員可能不會將它們提供給代碼(對外部世界),但重點是要知道駕駛員知道累加器的當前值(延遲了執行者心跳)。


BTW,問題是關於工作節點是蓄電池更新的邊界但實際上這是一個單獨的任務,創造了蓄電池更新的可見性邊界。如果你有一個或兩個工作節點(帶有一個或多個執行程序),這並不重要,因爲你也不會在單個執行程序上看到累加器更新。

累加器更新本地的任務,它在驅動程序和任務的自由裁量權有關的任何更新累加器被告知。

相關問題