Java 奇怪的榛猫IMap#put()行为
我的基于Hazelcast的程序可以在两种模式下工作:提交者和工作者 提交者通过一些键将一些POJO放入分布式映射,例如:Java 奇怪的榛猫IMap#put()行为,java,multithreading,hazelcast,hazelcast-imap,Java,Multithreading,Hazelcast,Hazelcast Imap,我的基于Hazelcast的程序可以在两种模式下工作:提交者和工作者 提交者通过一些键将一些POJO放入分布式映射,例如:hazelcastInstance.getMap(映射名称).put(键,值) Worker有一个无限循环(带有Thread.sleep(1000L);内部超时),它必须处理映射中的实体。现在我只是在这个循环中打印地图大小 现在问题来了。我启动worker应用程序。然后我同时启动四个提交者(每个提交者向映射添加一个条目并终止其工作)。但在所有提交者应用程序完成后,worker
hazelcastInstance.getMap(映射名称).put(键,值)代码>
Worker有一个无限循环(带有Thread.sleep(1000L);
内部超时),它必须处理映射中的实体。现在我只是在这个循环中打印地图大小
现在问题来了。我启动worker应用程序。然后我同时启动四个提交者(每个提交者向映射添加一个条目并终止其工作)。但在所有提交者应用程序完成后,worker应用程序打印任意大小:有时它检测到只添加了一个条目,有时两个,有时三个(实际上它从未看到所有四个条目)
这个简单的流程有什么问题?我在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);
}
提交人1:
Before: tasksMap.size() = 0
After: tasksMap.size() = 1
提交人2:
Before: tasksMap.size() = 1
After: tasksMap.size() = 4
提交人3:
Before: tasksMap.size() = 1
After: tasksMap.size() = 2
提交人4:
Before: tasksMap.size() = 3
After: tasksMap.size() = 4
嗯,我想,我已经解决了问题。据我所知,hazelcastInstance.getMap
返回的分布式IMap
不保证在集群中的所有现有节点上复制数据:数据的某些部分可能会复制到某些节点,另一部分-复制到另一个节点。这就是为什么在我的示例中,一些提交的任务并没有复制到worker节点(永久工作),而是复制到一些其他提交者,这些提交者在提交后终止其执行。因此,这些条目在提交者退出时丢失
我通过将hazelcastInstance.getMap
替换为hazelcastInstance.getReplicatedMap
解决了这个问题。此方法返回ReplicatedMap
,AFAIK保证将放置在其中的条目复制到群集的all节点。因此,现在我的系统中一切正常。IMap::size方法是一种估计,无论如何,它最终应该会稳定下来。你能分享更多的代码吗?@noctarius,我已经更新了这个问题。你的代码是否使用嵌入成员,他们在提交值后是否真的停止了?我可以想象成员在离开时迅速离开集群以满足备份要求。@DmytroTitov是您的提交者和工作进程,使用Hazelcast客户端api连接到集群,还是在集群节点上运行?如果在提交程序进程中在map.putIfAbsent
之前和之后打印,报告的大小是多少?@Siddharth它们在同一集群上运行。我在工人和四个提交者身上记录了地图大小(参见问题的更新)。
Before: tasksMap.size() = 1
After: tasksMap.size() = 2
Before: tasksMap.size() = 3
After: tasksMap.size() = 4