-
Notifications
You must be signed in to change notification settings - Fork 588
Open
Description
ehcache 3.10.9
In the mixed mode of disk and heap in ehcache, a multi-threaded high-concurrency call to the getAll() method throws errors:
java.lang.UnsupportedOperationException and java.lang.OutOfMemoryError: Cannot Reserve 316102 bytes of direct buffer memory (calculated: 133907512, limit: 134217728)
used
- Disk persistence: .with(CacheManagerBuilder.persistence())
- Hybrid Storage: heap + disk
CallinggetAllin a single thread works fine, but under high-concurrency stress testing, it occasionally throws an exceptionjava.lang.UnsupportedOperationExceptionwhen invokingsetLastAccessTimeunderOnHeapStore
After testing, it was found that using pure heap storage does not have this problem. Changing to for+get traversal query or adding synchronized(LOCK) to the getAll method in disk persistence mode can solve this problem.
It seems that there is a concurrency issue with setting access time records in disk mode. Is there a more elegant way? Is it caused by a configuration error
Here is a unit test
package com.huawei.ows.crdm.meta.data.metadata.metaCache.build;
import com.alibaba.fastjson.JSONObject;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.expiry.ExpiryPolicy;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class EhcacheTest {
private static final CacheManager cacheManager;
private static final Cache<String, JSONObject> METADATA_CACHE;
private static final Object CACHE_LOCK = new Object();
static {
cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.with(CacheManagerBuilder.persistence("/opt/mateinfo/temp/ehcache/metadata"))
.withCache("metadata-dict",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, JSONObject.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(3000, EntryUnit.ENTRIES)
.disk(500, MemoryUnit.MB, true)).withExpiry(ExpiryPolicy.NO_EXPIRY))
.build(true);
METADATA_CACHE = cacheManager.getCache("metadata-dict", String.class, JSONObject.class);
}
@Test
public void test_ehcache_loop_error() {
JSONObject jsonObject = new JSONObject();
METADATA_CACHE.put("1002-1", jsonObject);
METADATA_CACHE.put("1002-2", jsonObject);
METADATA_CACHE.put("1002-3", jsonObject);
METADATA_CACHE.put("1002-4", jsonObject);
METADATA_CACHE.put("1002-5", jsonObject);
METADATA_CACHE.put("1002-6", jsonObject);
Runnable task = () -> {
for (int i = 0; i < 30; i++) {
HashSet<String> keys = new HashSet<>(
Arrays.asList("1002-1", "1002-2", "1002-3", "1002-4", "1002-5", "1002-6"));
Collection<JSONObject> values = METADATA_CACHE.getAll(keys).values();
}
};
for (int i = 0; i < 1000; i++) {
Thread thread = new Thread(task, "thread-" + i);
thread.start();
}
}
public static Map<String, JSONObject> safeGetAll(Set<String> keys) {
synchronized (CACHE_LOCK) {
return METADATA_CACHE.getAll(keys);
}
}
}Exception in thread "thread-36" java.lang.UnsupportedOperationException
at org.ehcache.impl.internal.store.heap.OnHeapStore$Fault.setLastAccessTime(OnHeapStore.java:1118)
at org.ehcache.core.spi.store.AbstractValueHolder.accessed(AbstractValueHolder.java:98)
at org.ehcache.impl.internal.store.heap.OnHeapStrategy$NoExpirationStrategy.setAccessAndExpiryTimeWhenCallerOutsideLock(OnHeapStrategy.java:194)
at org.ehcache.impl.internal.store.heap.OnHeapStore.get(OnHeapStore.java:290)
at org.ehcache.impl.internal.store.heap.OnHeapStore.bulkGetOrComputeIfAbsent(OnHeapStore.java:967)
at org.ehcache.impl.internal.store.tiering.TieredStore.bulkComputeIfAbsent(TieredStore.java:364)
at org.ehcache.core.Ehcache.doGetAllInternal(Ehcache.java:101)
at org.ehcache.core.EhcacheBase.getAllInternal(EhcacheBase.java:343)
at org.ehcache.core.EhcacheBase.getAll(EhcacheBase.java:329)
at com.huawei.ows.crdm.meta.data.metadata.metaCache.build.EhcacheTest.lambda$test_ehcache_loop_error$0(EhcacheTest.java:56)
at java.base/java.lang.Thread.run(Thread.java:1583)
java.lang.UnsupportedOperationException
at org.ehcache.impl.internal.store.heap.OnHeapStore$Fault.setLastAccessTime(OnHeapStore.java:1118)
at org.ehcache.core.spi.store.AbstractValueHolder.accessed(AbstractValueHolder.java:98)
at org.ehcache.impl.internal.store.heap.OnHeapStrategy$NoExpirationStrategy.setAccessAndExpiryTimeWhenCallerOutsideLock(OnHeapStrategy.java:194)
at org.ehcache.impl.internal.store.heap.OnHeapStore.get(OnHeapStore.java:290)
at org.ehcache.impl.internal.store.heap.OnHeapStore.bulkGetOrComputeIfAbsent(OnHeapStore.java:967)
at org.ehcache.impl.internal.store.tiering.TieredStore.bulkComputeIfAbsent(TieredStore.java:364)
at org.ehcache.core.Ehcache.doGetAllInternal(Ehcache.java:101)
at org.ehcache.core.EhcacheBase.getAllInternal(EhcacheBase.java:343)
at org.ehcache.core.EhcacheBase.getAll(EhcacheBase.java:329)
at com.huawei.ows.crdm.meta.data.metadata.metaCache.build.EhcacheTest.lambda$test_ehcache_loop_error$0(EhcacheTest.java:56)
at java.base/java.lang.Thread.run(Thread.java:1583)
Metadata
Metadata
Assignees
Labels
No labels