当前位置: 首页 > 知识库问答 >
问题:

EhCache永恒的行为不如预期

昝涛
2023-03-14

我的要求是有基于磁盘的缓存。如果缓存内存已满,我希望将LRU元素推送到磁盘。然后,如果磁盘上的文件已满,我希望驱逐磁盘上的LRU元素。这是一个非常简单的要求,但是我无法使用EhCache来实现。

我使用EhCache(2.10.1)进行以下配置:

 <defaultCache name="default"
       maxBytesLocalHeap="50m"
       maxBytesLocalDisk="100g"
       eternal="true"
       timeToIdleSeconds="0"        
       timeToLiveSeconds="0"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU">
       <persistence strategy="localTempSwap"/>
 </defaultCache>

我的期望是,当缓存被填满时(即缓存大小超过50M),我希望将LRU元素推送到文件中,从而为内存中的新元素创建一些空间。

然而,这不是EhCache的工作方式,我做了一个示例测试来检查缓存中的元素计数:

公共静态 void main(String[] args) 抛出异常 {

ArrayList<String> keys = new ArrayList<String>();
CacheManager cacheManager;
FileInputStream fis = null;
try {
    fis = new FileInputStream(
            new File("src/config/ehcache.xml").getAbsolutePath());
    cacheManager = CacheManager.newInstance(fis);
}
finally {
    fis.close();
}

  java.lang.Runtime.getRuntime().addShutdownHook(new Thread(){
      @Override
    public void run() {

          try
          {
              System.out.println("Shutting down Eh Cache manager !!");
                 cacheManager.clearAll();
                 cacheManager.shutdown();
                 System.out.println("done !!");

          }catch(Exception e)
          {
              e.printStackTrace();
          }
                      }
  });

System.out.println("starting ...");
System.out.println(System.getProperty("java.io.tmpdir"));

cacheManager.addCache("work_item_111");

Cache ehCache = cacheManager.getCache("work_item_111");

long start_outer = System.currentTimeMillis();
for(int i =0;i<30;i++)
{
    long start = System.currentTimeMillis();
    String key = UUID.randomUUID().toString();
    ehCache.put(new Element(key, getNextRandomString()));
    keys.add(key);
    //System.out.println("time taken : " + (System.currentTimeMillis()- start));
    System.out.println((System.currentTimeMillis()- start) +" - " + (ehCache.getStatistics().getLocalDiskSizeInBytes()/1024/1024) + " - " +(ehCache.getStatistics().getLocalHeapSizeInBytes()/1024/1024));
}
System.out.println("time taken-total : " + (System.currentTimeMillis()- start_outer));
System.out.println(ehCache.getSize());

System.out.println("disk size : " +ehCache.getStatistics().getLocalDiskSizeInBytes()/1024/1024);
System.out.println("memory size : " +ehCache.getStatistics().getLocalHeapSizeInBytes()/1024/1024);

    Iterator<String> itr = keys.iterator();
    int count =0;
    while(itr.hasNext())
    {
        count++;
        String key = itr.next();
        if(ehCache.get(key) == null)
        {
            System.out.println("missingg key : " + key);
        }
    }
    System.out.println("checked for count :" + count);

}

在将30个元素放入缓存后(每个元素的大小大约为。4mb),我只能在缓存中看到7个元素(ehCache.getSize()返回7),并且我也没有看到磁盘上的文件在增长。

如果我在这里遗漏了什么,任何EhCache专家都能帮我吗。谢谢

共有2个答案

施凡
2023-03-14

面临同样的问题。在循环中,我使用缓存配置添加了10k个元素

 cacheConfiguration.maxBytesLocalHeap(1, MemoryUnit.MEGABYTES);
        cacheConfiguration.diskSpoolBufferSizeMB(10);
//        cacheConfiguration.maxEntriesLocalHeap(1);
        cacheConfiguration.name("smallcache");
        config.addCache(cacheConfiguration);
        cacheConfiguration.setDiskPersistent(true);
        cacheConfiguration.overflowToDisk(true);
        cacheConfiguration.eternal(true);

当maxBytesLocalHeap增加到10时,它是好的,当使用maxEntriesLocalHeap而不是maxBytes并且它甚至被设置为值1 (item)时,它工作起来没有问题。

版本 2.6

这是Ehcache设置为永恒但无论如何都会忘记元素吗?

爱海
2023-03-14

首先,关于EhCache拓扑:

  • Ehcache背后的分层模型强制自至少2.6起,所有映射始终存在于最低层,即您案例中的磁盘中。

这意味着它不再是一个溢出模型。

现在,关于为什么您的测试行为与您预期的不同:

  • EhCache2. x磁盘层将密钥保留在内存中,当您的堆是内存大小时,密钥占用的空间量将从该容量中减去。
  • Ehache2. x异步写入磁盘,并且执行此操作的队列有限。虽然在大多数用例中这不是问题,但在测试中的如此紧密的循环中,您可能会达到这些限制并通过逐出内联来放置缓存。

因此,为了更好地了解正在发生的事情,请查看调试中的Ehcache日志,看看到底发生了什么。如果看到逐出,只需以较慢的速度循环或增加磁盘写入队列的某些设置,例如缓存元素上的 diskSpoolBufferSizeMB 属性。

 类似资料:
  • 问题内容: 我正在尝试配置Ehcache(2.5版),使其永远不会忘记项目。我正在以编程方式进行配置,但没有涉及任何配置XML文件。通过设置,我的理解是,只有在我磁盘空间不足或超过(或应用程序终止)的情况下,才可以从缓存中删除项目。但是,此测试程序未显示该行为: 因此,在将100万个元素添加到缓存后(我告诉它会溢出到足够大的数量级的磁盘上)之后,最后我只剩下3276个项目。这是怎么回事 问题答案:

  • 有人说:“Plan9 会取代 UNIX,Mach 会取代 Linux 内核。” 但是你如果是一个深入体会了 UNIX 的人,你就会知道:UNIX 的思想是永恒的,不管时过境迁,Plan9 是否代替 UNIX,UNIX 的灵魂都会在 Plan9 身上现形! 我为同一个设备写过 Linux 内核和 Windows VxD 驱动程序。写 Linux 驱动程序时,我对 UNIX 设计的完美的一致性,远见性

  • 我有一个选择一个图像的意图(我在一个片段中这样称呼它): 在我的活动中: 输出:OnActivityResult:请求代码:66084 OnActivityResult:Result:-1成功=true 正如您所看到的,结果是成功的,但请求代码发生了更改。所以我无法查证是什么请求。

  • 我使用的是ehcache 1.2.3。由于缓存大小是根据“元素”指定的,缓存占用的内存可能会有很大差异(ehcache与hibernate一起使用,并且还保存标准查询缓存,其中查询返回大小可能会有所不同的结果集)。我的问题是:如果JVM内存不足会发生什么。阅读ehcache的变更日志给我的印象是,最初它使用的是软引用,但由于java 1.4正在大力清理它们,软引用最终被删除了。因此,如果缓存太大,

  • 在实用服务中,我有两个功能foo和bar。js 在我的测试文件中,我导入了实用ervice.js并窥探了条形图函数。我期望调用间谍计数为1,因为foo被称为,但它是0。如果我错过了什么,请建议。

  • 问题内容: 我正在尝试在我的工作原型中实现EHCache,在该原型中我有一个 javax.persistence.Entity,它 表示数据库中的表(MySQL,mysql-connector-java-5.1.20.jar),该XML作为XML提供给消费者。 我面临的问题是, 即使EHCache将查询结果存储在memory上 ,Hibernate似乎仍从数据库中检索数据。 我正在使用EHCach