我想知道是否有人能解釋我的代碼出了什麼問題。 我有一個IgniteCache Long-> Object []這是一種批處理機制。使用CacheEntryProcessor和修改緩存條目時出現奇怪的內存使用情況
緩存是onheap,分區並配置了一個備份。
我想修改緩存項值數組中的一些對象。 所以我寫了當集羣裝入數據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)
行,它將修改後的數組存儲回緩存中一切正常,除了數據不會被複制,因爲緩存不知道更改 - 更新是隻有主節點:(上可見
誰能告訴我怎麼做工作?有什麼不對的這種做法?
當然,我知道使用大堆時存在的不同問題,但到目前爲止,它對我們來說並沒有什麼大不了的。我們在內存映射減少作業中運行,這些作業爲存儲在緩存中的對象創建了一些統計信息 - 在給定相同硬件設置的情況下,堆上操作比堆外簡單快捷 - 我們始終都會對所有數據進行處理。你能解釋一下entry.setValue是如何工作的嗎?這次通話背後發生了什麼?對我來說,它看起來像必須有一個對象創建或序列化的副本,因爲我注意到對象出現在舊版本中(必須由於它們的大小)。 – Bart
詢問是因爲我正在修改原始數組而不是創建新對象並通過setValue存儲它們。根據setValue的代碼,它將oldVal分配給前一個值,val分配給新的值,所以我想知道新對象來自哪裏。 – Bart
是的,獲取值時會創建副本,並且'setValue'用新值替換舊值。 –