Java 在Hazelcast中存储地图的有效方法?
我目前正在使用Hazelcast通过网络分发我的数据。该实现使用我要存储的对象的IMap。然而,这些对象中的每一个本质上都只是一个HashMap,所以我一直在想,是否有一种更有效的方法可以使用Hazelcast分发“map of maps” 我已经阅读了他们的bug追踪器,但是在实现该功能方面没有取得任何进展 如果Hazelcast的核心功能没有这一点,那么除了我目前的“Java 在Hazelcast中存储地图的有效方法?,java,hazelcast,Java,Hazelcast,我目前正在使用Hazelcast通过网络分发我的数据。该实现使用我要存储的对象的IMap。然而,这些对象中的每一个本质上都只是一个HashMap,所以我一直在想,是否有一种更有效的方法可以使用Hazelcast分发“map of maps” 我已经阅读了他们的bug追踪器,但是在实现该功能方面没有取得任何进展 如果Hazelcast的核心功能没有这一点,那么除了我目前的“IMap”方法之外,还有什么更有效的方法来管理这种数据结构吗 该实现使用我要存储的对象的IMap。然而,这些对象中的每一个本质
IMap
”方法之外,还有什么更有效的方法来管理这种数据结构吗
该实现使用我要存储的对象的IMap。然而,这些对象中的每一个本质上都只是一个HashMap
与使用IMap存储HashMap不同,您可能只需在主IMap中存储与某个键对应的HashMap的just标识符,并在Hazelcast中存储所有子映射
而不是IMap
使用IMap
并使用hazlecastance.getMap(SomeStringId)
获得相应的HashMap
——这样,在变异后您仍然需要将值放回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/值(例如,查找employee 1234的所有属性)
另一种防止进行不必要的序列化/反序列化的方法是将映射作为值与通过EntryProcessor的所有访问相结合。通过这种方式,您可以很好地控制EntryProcessor发送/返回的数据,而不必担心数据竞争,因为这是EntryProcessor提供的现成数据。API可能没有那么漂亮,但它可能会以一种非常有效的方式完成这个任务。在这种情况下,我建议使用内存中的对象格式。这种方法的另一个优点是很容易获得所有值,因为它们都分组在hashmap值中。但是,如果列的数量是“无限”的,这可能会导致问题,因为hashmap值不是分布式的。这不是复合键方法的问题
因此,这在一定程度上取决于您想要的用例 我知道现在回答您的问题可能太晚了,但我在尝试为聊天服务创建自己的分布式用户会话实现时遇到了同样的问题 因此,我所做的是将我的映射序列化为字节[],然后将其持久化到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 distributedMap=hazelcast.getMap(地图名称);
Map myMap=newhashmap();
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
ObjectOutputStream oos=新的ObjectOutputStream(BAS);
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();
IMap distributedMap=hazelcast.getMap(地图名称);
字节[]原始=distributedMap.get(sessionId);
ByteArrayInputStream bais=新的ByteArrayInputStream(字节);
ObjectInputStream ois=新ObjectInputStream(BAI);
Map myMap=(Map)ois.readObject();
然后在我拿回我的地图之后,我可以用它做任何事情。我希望这将帮助任何需要像我这样做的人。因为Hazelcast Map不会将对象的状态视为给定的值,如果在Hashmap中添加或删除值,则将IMap与Hashmap对象(值)一起使用毫无意义,而这些值的更改不会在集群中共享 Hazelcast仅共享其容器中的引用更改。因此,您应该有一个带有单个连接键的IMap,如key1+“WhatEverString”+key2
如果每次更改内部HashMap的状态时都将内部HashMap的引用提供给IMap,Hazelcast将重新序列化整个内部映射,它的性能将降低。为什么不创建一个容器类来替换
HashMap
?您可以在那里实现get、add和其他Map方法。如果我不得不猜测当前实现中的低效,那就是Hazelcast没有深入查看内部地图。因此,当我需要更新内部贴图中的对象时,我必须取出该对象,根据需要更改值,然后在Hazelcast IMap中替换整个对象。我想知道是否有一种更有效的方法,Hazelcast可以更好地了解它所处理的内容。如果对象是可变的,那么直接get()
-绑定对象并对其进行处理(而不是像您提到的那样做)应该不会有任何问题不幸的是,Hazelcast的情况并非如此——对象是可变的,但直接对其所做的更改似乎被Hazelcast忽略,并且不会通过网络传播。我的Hazelcast配置中是否缺少某些内容?(请参阅中标题为“如何反映值修改”的项目。)感谢提供信息。我已经实现了EntityProcessor建议,它大大减少了应用程序的内存使用!由于我经常需要访问“内部”映射中的所有值,我不确定复合键解决方案是否有效,但我会尝试一下。如果需要访问多个/全部,复合键可能不是最佳解决方案。因为对于每把钥匙,你都需要做一个潜在的远程调用。通过将映射作为值与条目处理器结合使用,您可以防止这种情况。Hazelcast还提供了多映射,您可以根据单个键存储多个对象(如果它适合您的用例)。请检查下面的链接以获取d