ehcache未使用maxElementsInMemory

ehcache未使用maxElementsInMemory,memory,ehcache,Memory,Ehcache,我有一个相当简单的缓存配置: <cache name="MyCache" maxElementsInMemory="200000" eternal="false" timeToIdleSeconds="43200" timeToLiveSeconds="43200" overflowToDisk="false" diskPersistent="false" memoryStoreEvictionPolicy="LRU"

我有一个相当简单的缓存配置:

 <cache name="MyCache"
    maxElementsInMemory="200000"
    eternal="false"
    timeToIdleSeconds="43200" 
    timeToLiveSeconds="43200"
    overflowToDisk="false"
    diskPersistent="false"
    memoryStoreEvictionPolicy="LRU" 
    />

我使用缓存的方式如下:

public MyResponse processRequest(MyRequest request) {
    Element element = myCache.get(request);
    if (element != null) {
        return (MyResponse)element.getValue();
    } else {
        MyResponse response = remoteService.process(request); 
        myCache.put(new Element(request, response));
        return response;
    }
}
logger.debug("Cache name: " + myCache.getName());
logger.debug("Max elements in memory: " + myCache.getMaxElementsInMemory());
logger.debug("Memory store size: " + myCache.getMemoryStoreSize());
logger.debug("Hit count: " + myCache.getHitCount());
logger.debug("Miss count: " + myCache.getMissCountNotFound());
logger.debug("Miss count (because expired): " + myCache.getMissCountExpired());

每次调用processRequest()方法10000次,我都会记录有关缓存的统计信息,如下所示:

public MyResponse processRequest(MyRequest request) {
    Element element = myCache.get(request);
    if (element != null) {
        return (MyResponse)element.getValue();
    } else {
        MyResponse response = remoteService.process(request); 
        myCache.put(new Element(request, response));
        return response;
    }
}
logger.debug("Cache name: " + myCache.getName());
logger.debug("Max elements in memory: " + myCache.getMaxElementsInMemory());
logger.debug("Memory store size: " + myCache.getMemoryStoreSize());
logger.debug("Hit count: " + myCache.getHitCount());
logger.debug("Miss count: " + myCache.getMissCountNotFound());
logger.debug("Miss count (because expired): " + myCache.getMissCountExpired());
…我看到了大量的点击,这告诉我它正在工作。
…然而,我看到的是,几个小时后,getMemoryStoreSize()开始超过GetMaxElementsMemory()。最终,它变得越来越大,并使jvm变得不稳定,因为GC开始不间断地执行完整的GCs来回收内存(我有一个相当大的上限集)。当我分析堆时,它指向占用大部分空间的LRU的SpoolingLinkedHashMap

我确实有很多请求命中了这个缓存,我的理论是ehcache的LRU算法可能跟不上在元素满时逐出元素。我尝试了LFU策略,它还导致内存存储超过了maxElements


然后我开始查看ehcache代码,看看是否可以证明我的理论(在LruMemoryStore$SpoolingLinkedHashMap中):

…从这里看是ok,然后看execute()方法:

…看起来它实际上并没有逐出(不管名称如何),而是依赖调用方逐出。因此,我查看了put()方法的实现,但没有看到它调用它。很明显,我在这里遗漏了一些东西,希望能得到一些帮助


谢谢

我觉得您的配置很好。唯一需要的是使用正确的键进行缓存

不要将完整的请求对象作为缓存的密钥。从请求对象中放入一些唯一的值。例如:

MyResponse response = remoteService.process(request); 
myCache.put(new Element(request.getCustomerID(), response));
return response;

这应该对你有用。缓存不工作的原因是每次请求对象都是新对象;它从未从缓存中找到响应,因此一直添加到缓存中。

MaxElementsMemory
属性已被弃用,请改用
maxEntriesLocalHeap

那么您使用的是旧式LRU存储吗?或者您当前使用的是什么版本?我会尝试更新,ehcache当前的版本是2.5.0。您的版本已于2006年9月发布
MyResponse response = remoteService.process(request); 
myCache.put(new Element(request.getCustomerID(), response));
return response;