我想知道是否有人可以解释我的代码出了什么问题。 我有一个Long-> Object []的IgniteCache,这是一种批处理机制。
缓存已开启,已分区且已配置一个备份。
我想修改缓存条目值数组中的一些对象。 所以我编写并实现了CacheEntryProcessor
@Override
public Object process(MutableEntry<Long, Object[]> entry, Object... arguments)
throws EntryProcessorException {
boolean updated = false;
int key = (int)arguments[0];
Set<Long> someIds = Ignition.ignite().cluster().nodeLocalMap().get(key);
Object[] values = entry.getValue();
for (int i = 0; i < values.length; i++) {
Person p = (Person) values[i];
if (someIds.contains(p.getId())) {
p.modify();
if (!updated) {
updated = true;
}
}
}
if (updated) {
entry.setValue(values);
}
return null;
}
}
当群集加载数据时,每个节点消耗大约20GB的堆。 当我在多节点集群上使用cache.invokeAll运行缓存处理器时,我有一个疯狂的内存行为 - 当处理器运行时,我看到内存使用率甚至达到48GB或更高,最终导致节点与集群分离,因为GC也是长。
但是,如果我删除entry.setValue(values)
行,它将修改后的数组存储到缓存中,除了由于缓存不知道更改而不会复制数据这一事实外,一切都还可以。更新仅在主节点上可见:(
有谁能告诉我如何让它发挥作用?这种方法有什么问题?
答案 0 :(得分:0)
首先,我不建议分配大堆大小。即使一切正常,这很可能会导致GC暂停。基本上,JVM在达到某个阈值之前不会清理内存,当它到达时,会收集很多垃圾。尝试切换到堆外或启动更多Ignite节点。
在更新条目的情况下生成更多垃圾的事实非常有意义。基本上每次更新时都会用旧值替换旧值,旧值会变成垃圾。
如果这些都没有帮助,请抓住堆转储并检查占用内存的是什么。