Apache Ignite 缓存驱逐仍在内存中
Apache Ignite Cache eviction still in memory
在我们的 apache ignite 集群的稳定性测试中,我们遇到了一个与内存相关的问题,其中使用的内存堆 space 增加到 100% 并且没有像我们预期的那样下降。这就是我们所做的:
创建了一个缓存,逐出策略为 FifoEvictionPolicy(最大值:10000,batchSize:100)
20 个并发线程在几个小时内一遍又一遍地执行以下场景:
向缓存中添加了一个唯一条目,然后获取该值以验证它是否已添加。
此场景在测试期间创建了大约 230 万个条目。
我们的预期是由于我们在最多 10000 个条目时相当严格的驱逐政策,内存应该是稳定的。但是,内存一直在上升,直到达到最大堆大小。请参阅随附的内存图:
我们的问题是:
为什么即使已完成逐出,条目使用的内存仍会分配?
要补充的一件事是,我们执行了相同的测试,但在添加之后删除了条目。内存现在稳定了:
更新测试用例和评论。
下面你会找到一个简单的junit测试来证明内存泄漏。 @a_gura 似乎是正确的——如果我们禁用 ExpiryPolicy,事情就会按预期工作。但是如果我们启用 ExpiryPolicy,堆似乎会在 ExpiryPolicy-duration 内被填满。测试用例:
public class IgniteTest {
String cacheName = "my_cache";
@Test
public void test() throws InterruptedException {
IgniteConfiguration configuration = new IgniteConfiguration();
Ignite ignite = Ignition.start(configuration);
//create a large string to use as test value.
StringBuilder testValue = new StringBuilder();
for (int i = 0; i < 10*1024; i ++) {
testValue.append("a");
}
CacheConfiguration cacheCfg = new CacheConfiguration();
cacheCfg.setName(cacheName);
cacheCfg.setEvictionPolicy(new FifoEvictionPolicy<>(10_000, 100));
Duration duration = new Duration(TimeUnit.HOURS, 12);
cacheCfg.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(duration));
cacheCfg.setCacheMode(CacheMode.LOCAL);
cacheCfg.setBackups(0);
Cache<Object, Object> cache = ignite.getOrCreateCache(cacheCfg);
String lastKey = "";
for (int i = 0; i < 10_000_101; i++){
String key = "key#"+i;
String value = testValue + "value#"+i;
log.trace("storing {} {}", key, value);
if (i % 1_000 == 0) {
log.debug("storing {}", key);
}
cache.put(key, value);
lastKey = key;
Thread.sleep(1);
}
String verifyKey = "key#1";
Assert.assertThat("first key should be evicted", cache.containsKey(verifyKey), CoreMatchers.is(false));
Assert.assertThat("last key should NOT be evicted", cache.containsKey(lastKey), CoreMatchers.is(true));
ignite.destroyCache(cacheName);
}
}
这已在 Ignite 1.8 中修复:https://issues.apache.org/jira/browse/IGNITE-3948。
感谢提交错误的@a_gura 和开发团队。
在我们的 apache ignite 集群的稳定性测试中,我们遇到了一个与内存相关的问题,其中使用的内存堆 space 增加到 100% 并且没有像我们预期的那样下降。这就是我们所做的:
创建了一个缓存,逐出策略为 FifoEvictionPolicy(最大值:10000,batchSize:100) 20 个并发线程在几个小时内一遍又一遍地执行以下场景: 向缓存中添加了一个唯一条目,然后获取该值以验证它是否已添加。 此场景在测试期间创建了大约 230 万个条目。
我们的预期是由于我们在最多 10000 个条目时相当严格的驱逐政策,内存应该是稳定的。但是,内存一直在上升,直到达到最大堆大小。请参阅随附的内存图:
我们的问题是: 为什么即使已完成逐出,条目使用的内存仍会分配?
要补充的一件事是,我们执行了相同的测试,但在添加之后删除了条目。内存现在稳定了:
更新测试用例和评论。
下面你会找到一个简单的junit测试来证明内存泄漏。 @a_gura 似乎是正确的——如果我们禁用 ExpiryPolicy,事情就会按预期工作。但是如果我们启用 ExpiryPolicy,堆似乎会在 ExpiryPolicy-duration 内被填满。测试用例:
public class IgniteTest {
String cacheName = "my_cache";
@Test
public void test() throws InterruptedException {
IgniteConfiguration configuration = new IgniteConfiguration();
Ignite ignite = Ignition.start(configuration);
//create a large string to use as test value.
StringBuilder testValue = new StringBuilder();
for (int i = 0; i < 10*1024; i ++) {
testValue.append("a");
}
CacheConfiguration cacheCfg = new CacheConfiguration();
cacheCfg.setName(cacheName);
cacheCfg.setEvictionPolicy(new FifoEvictionPolicy<>(10_000, 100));
Duration duration = new Duration(TimeUnit.HOURS, 12);
cacheCfg.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(duration));
cacheCfg.setCacheMode(CacheMode.LOCAL);
cacheCfg.setBackups(0);
Cache<Object, Object> cache = ignite.getOrCreateCache(cacheCfg);
String lastKey = "";
for (int i = 0; i < 10_000_101; i++){
String key = "key#"+i;
String value = testValue + "value#"+i;
log.trace("storing {} {}", key, value);
if (i % 1_000 == 0) {
log.debug("storing {}", key);
}
cache.put(key, value);
lastKey = key;
Thread.sleep(1);
}
String verifyKey = "key#1";
Assert.assertThat("first key should be evicted", cache.containsKey(verifyKey), CoreMatchers.is(false));
Assert.assertThat("last key should NOT be evicted", cache.containsKey(lastKey), CoreMatchers.is(true));
ignite.destroyCache(cacheName);
}
}
这已在 Ignite 1.8 中修复:https://issues.apache.org/jira/browse/IGNITE-3948。
感谢提交错误的@a_gura 和开发团队。