繁体   English   中英

使用Terracotta的EHCache如何处理从分布式堆中逐出?

[英]How does EHCache using Terracotta handle eviction from the distributed heap?

我们最近开始将EHCache与Terracotta结合使用,以为应用程序数据运行分布式数据缓存。 假设任何客户节点的堆内存约为2gb,而服务器节点的内存约为8gb。 我们每天产生大量数据,大约1.5gb。

通常,任何一个客户端都将使用特定日期的数据集(大约1.5gb),但是服务器显然必须保留所有这些数据集。

当堆变大时,我希望失效的工作方式基于LRU。 因此,如果任何特定的L1客户端缓存太大(例如,从day1切换到day2),我希望它会从L1的所有day1数据中退出。 如果L6在我们获得第6个数据集时变得太大,那么最早的数据集将完全过期。 对于生存时间或空闲时间值,我真的没有任何意见,因此我将其保留下来。

经过几天的研究,我认为这没有达到我的预期。 例如,我运行了一个L2 max元素为4的测试。我为其填充了四个元素。 然后我去提出第五个要素。 Cache.put()无异常返回,但是紧随其后的具有相同键的Cache.get()返回null!

所以我的问题是,如何让EHCache + Terracotta来做我想做的事情,或者至少要做些什么?

经过一番混乱之后,事实证明,神秘的行为取决于L1缓存是否了解L2缓存中的内容。 所附的单元测试旨在成对执行,该对中的每个元素都在单独的JVM中运行,以避免EHCache单身。

我认为行为良好的L1-> L2关系应该起作用的方式是,如果执行.put()时没有错误,则应该能够在没有问题的情况下立即执行相同键的get()。没有其他同时运行的线程弄乱了东西)。 但是,使用Terracotta EHCache时,如果该.put()需要撤消某些操作,则不会发生驱逐,并且put()会被静默忽略,除非L1客户端“知道”可以撤消的密钥。 在* JVM2测试中,它使用.getAllWithLoader()找出其他那些键,然后* JVM2测试按预期工作。

因此,为了解决原始问题,我们要做的是使它成为定期使客户端执行.getAllWithLoader()的方法。 然后,我们可以确保遵守所有驱逐规则。

package com.mine;

import java.io.Serializable;

import junit.framework.TestCase;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.TerracottaClientConfiguration;
import net.sf.ehcache.config.TerracottaConfiguration;

public class CacheEvictionTest extends TestCase {

    private static final String SERVER = "localhost:9510";
    private CacheManager cacheManager;
    private Cache cache;
    private final Serializable keyA = "a";
    private final Serializable keyB = "b";
    private final Serializable keyC = "c";

    @Override
    protected void setUp() throws Exception {
        Configuration configuration = new Configuration();
        TerracottaClientConfiguration terracottaConfig = new TerracottaClientConfiguration();
        terracottaConfig.setUrl(SERVER);
        configuration.addTerracottaConfig(terracottaConfig);

        int maxElementsInMemory = 1;
        int maxElementsOnDisk = 2;
        long timeToIdleSeconds = 15;
        long timeToLiveSeconds = 15;
        String cacheName = "TEST_CACHE";
        CacheConfiguration amoebaCache = new CacheConfiguration(cacheName, maxElementsInMemory).statistics(true)
                        .terracotta(new TerracottaConfiguration())
                        .logging(true)
                        .maxElementsOnDisk(maxElementsOnDisk)
                        .timeToIdleSeconds(timeToIdleSeconds)
                        .timeToLiveSeconds(timeToLiveSeconds);
        configuration.addCache(amoebaCache);
        configuration.addDefaultCache(new CacheConfiguration("default", 0));

        cacheManager = new CacheManager(configuration);
        cache = cacheManager.getCache(cacheName);
    }

    @Override
    protected void tearDown() throws Exception {
        if (cache != null) {
            cache.removeAll();
            cache.clearStatistics();
        }
    }

    public void testMaxElementOnDiskEvictionJVM1() throws Exception {
        cache.clearStatistics();

        cache.put(new Element(keyA, keyA));
        cache.put(new Element(keyB, keyB));

        cache = null;
    }

    public void testMaxElementOnDiskEvictionJVM2() throws Exception {
        assertEquals(2, cache.getSize());

        for (Object key : cache.getKeys()) {
            cache.get(key;
        }

        cache.put(new Element(keyC, keyC));

        assertEquals(2, cache.getSize());
        assertNotNull(cache.get(keyC));
    }

    public void testEvictsExpiredElementsFromDiskWhenNotInMemoryAndWeNeverKnewAboutItJVM1() throws Exception {
        cache.clearStatistics();
        cache.put(new Element(keyA, keyA));

        cache = null;
        cacheManager = null;
    }

    public void testEvictsExpiredElementsFromDiskWhenNotInMemoryAndWeNeverKnewAboutItJVM2() throws Exception {
        cache.clearStatistics();

        for (Object key : cache.getKeys()) {
            cache.get(key;
        }
        assertEquals(0, cache.getStatistics().getEvictionCount());

        Thread.sleep(20000);

        assertEquals(1, cache.getStatistics().getEvictionCount());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM