2016-04-24 43 views
14

我的基於Hazelcast的程序可以在兩種模式下工作:提交者和工作者。奇怪的Hazelcat IMap#put()行爲

發佈者通過一些關鍵,例如:hazelcastInstance.getMap(MAP_NAME).put(key, value);

工人具有一個無限循環(具有Thread.sleep(1000L);內部超時),必須從地圖處理實體提出一些POJO到分佈式映射。現在我只是在這個循環中打印地圖大小。

現在是這個問題。我開始工人應用程序。然後,我同時啓動四個提交者(每個添加一個條目到地圖並終止它的工作)。但是,在所有提交者應用完成後,工作者應用會打印任意大小:有時它會檢測到只添加了一個條目,有時是兩個,有時是三個(實際上從未看過全部四個條目)。

這個簡單的流程有什麼問題?我在Hazelcast文檔中看到put()方法是同步的,所以它保證在它返回後,將條目放置到分佈式映射中,並且被複制。但在我的實驗中似乎並不如此。

UPD(代碼)

發佈者:

public void submit(String key) { 
    Object mySerializableObject = ... 
    IMap<String, Object> map = hazelcastInstance.getMap(MAP_NAME); 
    map.putIfAbsent(key, mySerializableObject, TASK_TTL_IN_HOURS, TimeUnit.HOURS); 
} 

工人:

public void process() { 
    while (true) { 
     IMap<String, Object> map = hazelcastInstance.getMap(MAP_NAME); 
     System.out.println(map.size()); 

     // Optional<Map.Entry<String, Object>> objectToProcess = getObjectToProcess(); 
     // objectToProcess.ifPresent(objectToProcess-> processObject(id, objectToProcess)); 
     try { 
      Thread.sleep(PAUSE); 
     } catch (InterruptedException e) { 
      LOGGER.error(e.getMessage(), e); 
     } 
    } 
} 

我註釋掉 「處理」 部分本身,因爲現在我只是想獲得一致的地圖狀態。上面的代碼每次打印不同的結果,例如:「4,3,1,1,1,1,1 ...」(因此它甚至可以看到4個提交的任務一會兒,但是然後它們消失) 。

UPD(日誌)

工人:

... 
tasksMap.size() = 0 
tasksMap.size() = 0 
tasksMap.size() = 0 
tasksMap.size() = 0 
tasksMap.size() = 1 
tasksMap.size() = 2 
tasksMap.size() = 2 
tasksMap.size() = 2 
tasksMap.size() = 2 
tasksMap.size() = 2 
... 

發佈者1:

Before: tasksMap.size() = 0 
After: tasksMap.size() = 1 

發佈者2:

Before: tasksMap.size() = 1 
After: tasksMap.size() = 4 

Submi tter 3:

Before: tasksMap.size() = 1 
After: tasksMap.size() = 2 

發佈4:

Before: tasksMap.size() = 3 
After: tasksMap.size() = 4 
+0

IMap :: size方法是一種估計,無論如何它應該最終穩定下來。你能分享更多的代碼嗎? – noctarius

+0

@noctarius,我已經更新了這個問題。 –

+0

您的代碼是否使用嵌入式成員,並且在提交值後實際停止了嗎?我可以想象會員可以快速離開集羣,以滿足休假時的備份要求。 – noctarius

回答

7

嗯,我想,我已經想通了這個問題。據我瞭解,由hazelcastInstance.getMap返回的分佈式IMap不保證數據在羣集中的所有現有節點上被複制:數據的某些部分可能被複制到某些節點,另一部分被複制到另一個節點。這就是爲什麼在我的示例中,一些提交的任務不是複製到工作節點(永久工作),而是複製到其他提交者,這些提交者在提交後終止執行。所以這些條目在提交者退出時丟失了。

我通過將hazelcastInstance.getMap替換爲hazelcastInstance.getReplicatedMap解決了此問題。此方法返回ReplicatedMap,AFAIK確保放入它的條目將被複制到集羣的所有節點。所以現在在我的系統中一切正常。