使用CacheEntryProcessor并修改缓存条目

时间:2017-01-05 19:03:15

标签: memory-leaks ignite

我想知道是否有人可以解释我的代码出了什么问题。 我有一个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)行,它将修改后的数组存储到缓存中,除了由于缓存不知道更改而不会复制数据这一事实外,一切都还可以。更新仅在主节点上可见:(

有谁能告诉我如何让它发挥作用?这种方法有什么问题?

1 个答案:

答案 0 :(得分:0)

首先,我不建议分配大堆大小。即使一切正常,这很可能会导致GC暂停。基本上,JVM在达到某个阈值之前不会清理内存,当它到达时,会收集很多垃圾。尝试切换到堆外或启动更多Ignite节点。

在更新条目的情况下生成更多垃圾的事实非常有意义。基本上每次更新时都会用旧值替换旧值,旧值会变成垃圾。

如果这些都没有帮助,请抓住堆转储并检查占用内存的是什么。