在 Hazelcast 中存储地图地图的有效方法?

Efficient way to store a Map of Maps in Hazelcast?

我目前正在使用 Hazelcast 通过网络分发我的数据。该实现使用我要存储的对象的 IMap。然而,这些对象中的每一个本质上只是一个 HashMap,所以我一直想知道是否有更有效的方法来使用 Hazelcast 分发 "map of maps"。

我已经阅读了 this long-forgotten issue 他们的错误跟踪器,但在实现该功能方面没有取得任何进展。

在没有将此作为核心 Hazelcast 功能的情况下,除了我当前的“IMap<String, HashMap<String, String>>”方法之外,是否还有更有效的管理此类数据结构的方法?

The implementation uses an IMap of objects that I want to store. However, each of these objects is essentially just a 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);

Hazelcast 不支持键、值的映射。但一种可能的解决方案是使用复合键:

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

但是,请注意。如果您需要访问许多值,因为每次访问都需要往返。另一个缺点是很难获得 key1 的所有 key2/values(例如,找到员工 1234 的所有属性)。

另一种防止不想要的行为的方法 serialization/deserialization 是将映射作为值与通过 EntryProcessor 的所有访问相结合。通过这种方式,您可以很好地控制 send/returned + 使用 EntryProcessor 的数据,您无需担心数据争用,因为这是开箱即用的 EntryProcessor 提供的。 API 可能不是那么漂亮,但它可能会以一种非常有效的方式达到目的。在这种情况下,我建议使用内存格式的 OBJECT。这种方法的另一个优点是很容易获得所有值,因为它们在 hashmap-value 中分组。但是,如果您有 'infinite' 列,这可能会导致问题,因为散列映射值未分发。这不是复合键方法的问题。

所以这在一定程度上取决于您的用例。

我知道现在回答您的问题可能为时已晚,但是当我尝试为我的聊天服务创建自己的分布式用户会话实现时遇到了同样的问题。

所以我所做的是将我的 Map 序列化为 byte[] 然后将其持久化到 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();

然后在我取回 Map 之后,我可以用它做任何事情。我希望这会帮助任何需要像我一样做的人。

由于 Hazelcast Map 不会将对象的状态视为给定值,因此如果您在 HashMap 内部添加或删除值,则将 IMap 与 Hashmap 对象(值)一起使用是没有意义的,更改不会在集群中共享。

Hazelcast 仅共享其容器中的引用更改。所以你应该有一个带有单个连接键的 IMap 作为 key1 + "WhatEverString"+ key2.

如果每次更改内部 HashMap 的状态时都将内部 HashMap 的引用提供给 IMap,Hazelcast 将重新序列化整个内部映射,并且性能会降低。