2015-07-06 68 views
1

我目前使用Hazelcast通過網絡分發我的數據。該實現使用我想要存儲的對象的IMap。但是,這些對象中的每一個本質上都只是一個HashMap,所以我一直在想是否有更高效的方式來使用Hazelcast分發「地圖映射」。在Hazelcast中存儲地圖的地圖的有效方法?

我已經在他們的bug跟蹤器上讀過this long-forgotten issue,但是在實現這個功能方面沒有任何進展。

在沒有這個作爲核心Hazelcast功能的情況下,除了我現有的「IMap<String, HashMap<String, String>>」方法之外,是否還有更有效的方式來管理這種數據結構?

+0

爲什麼不創建一個將替換'HashMap '的容器類?您可以在其中實現get,add和其他Map方法。 – Mackiavelli

+0

我這樣做 - 'HashMap '只是一個例子。如果我不得不猜測當前實施中效率低下的問題,那就是Hazelcast並沒有深入研究內部地圖。所以當我需要更新內部地圖中的對象時,我必須取出對象,根據需要更改值,然後替換Hazelcast IMap中的整個對象。我想知道是否有更有效的方式,Hazelcast可以更多地瞭解它處理的內容。 –

+0

如果對象是可變的,那麼你不應該有任何問題直接'get()' - 對象並在其上工作(與你必須做的相反) – Mackiavelli

回答

2

Hazelcast不支持密鑰,值的映射圖。但一種可能的解決方案是使用複合鍵:

String employeeId = "1234" 
String attribute = "name" 
map.put(employeeId+"#"+attribute, "peter") 

但是,要警告。如果您需要訪問許多值,因爲每次訪問都需要往返。另一個缺點是很難獲得關鍵字1的所有key2 /值(例如,查找僱員1234的所有屬性)。

另一種防止不必要的序列化/反序列化的方法是將map作爲值與通過EntryProcessor進行的所有訪問相結合。通過這種方式,您可以非常精確地控制正在發送/返回的數據,使用EntryProcessor您不必擔心數據爭用,因爲它是由EntryProcessor開箱即用的。 API可能不是那麼漂亮,但它可能會以非常有效的方式做到這一點。在這種情況下,我會建議使用內存格式的對象。這種方法的另一個優點是很容易得到所有的值,因爲它們被分組在hashmap-value中。但是,如果您的列數量「無限」,則可能會導致問題,因爲hashmap值未分配。這不是複合密鑰方法的問題。

因此,它取決於你的用例,你想要什麼。

+1

感謝您的信息。我已經實現了EntityProcessor建議,它已經大大減少了我的應用程序的內存使用量!由於我經常需要訪問「內部」映射中的所有值,所以我不確定組合鍵解決方案是否有效,但我會試一試。 –

+0

如果您需要訪問many/all,組合鍵可能不是最佳解決方案。因爲你需要爲每個密鑰做一個潛在的遠程通話。將地圖作爲值與入口處理器結合使用時,可以防止出現這種情況。 – pveentjer

2

該實現使用我想要存儲的對象的IMap。然而,每個對象的本質上只是一個HashMap

而不是使用IMAP存儲的HashMap你很可能只是在主IMAP存儲只是標識對應於某些關鍵的HashMap和存儲在Hazelcast所有子圖以及。

代替IMap<String, HashMap> 使用IMap<String, SomeStringId>,並得到相應的HashMapHazlecastInstance.getMap(SomeStringId) - 這樣,你仍然需要把值回Hazelcast變異後,但你只是把一個價值 - 而不是整個地圖。

IMap main = hazelcastInstance.getMap("Main"); 
String childMapName = main.get(key); 
IMap childMap = hazelcastInstance.getMap(childMapName); 
Object value = childMap.get(childKey); 
value.changeSmth(); 
childMap.put(chlidKey,value); 
2

我知道這可能來不及回答你的問題,但當我試圖爲我的聊天服務創建自己的分佈式用戶會話實現時,我遇到了同樣的問題。

所以我所做的就是我的序列化映射字節[]然後堅持到hazelcast的IMAP
檢查下面的代碼:

IMap<String, byte[]> distributedMap = hazelcast.getMap(MAP_NAME); 

Map<String, Serializable> myMap = new HashMap<String, Serializable>(); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(baos); 
oos.writeObject(myMap); 

distributedMap.put(sessionId, baos.toByteArray()); 

,當我嘗試檢索持久用戶會話,我做的是類似下面的代碼。

IMap<String, byte[]> distributedMap = hazelcast.getMap(MAP_NAME); 

byte[] raw = distributedMap.get(sessionId); 
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 
ObjectInputStream ois = new ObjectInputStream(bais); 
Map<String, Serializable> myMap = (Map<String, Serializable>) ois.readObject(); 

然後後,我讓我的地圖回來,我可以做任何事情。我希望這能幫助那些需要像我一樣做的人。

0

由於Hazelcast Map沒有將對象的狀態視爲給定的值,所以如果添加或刪除內部HashMap的值,則使用帶有Hashmap對象(值)的IMap將無法在集羣中共享這些更改。

Hazelcast只在其容器中共享引用更改。所以你應該有一個帶單個加入密鑰的IMap,作爲key1 +「WhatEverString」+ key2

如果您每次更改內部HashMap的狀態時都將內部HashMap引用到IMap,Hazelcast將重新整理內部地圖的整體,並且性能會降低。