2016-04-21 22 views
0

我的要求是擁有基於磁盤的緩存。如果緩存內存已滿,我需要將LRU元素推送到磁盤。然後如果磁盤上的文件已滿,那麼我希望磁盤上的LRU元素被驅逐。這是非常簡單的要求,但是我無法使用EhCache實現此目的。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元素(S )被推送到文件,因此在內存中爲新元素創建一些空間。

然而,這不是的Ehcache是​​如何工作的,我做了一個樣本測試,以檢查元素計數緩存:

公共靜態無效的主要(字串[] 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專家都可以幫助我嗎?謝謝。

回答

0

首先,關於的Ehcache拓撲:

  • 因爲至少2.6是所有映射出現在最低層背後的Ehcache的分層模型強制執行,磁盤你的情況,在任何時候。

這意味着它不再是溢出模型。

現在,爲什麼你的測試行爲不同於你所期望的:

  • 的Ehcache 2.x的磁盤層離開鍵在內存中,當你的堆是內存大小,空間量的關鍵佔據從該容量中減去。
  • Ehcache 2.x異步寫入磁盤,並限制隊列這樣做。雖然這在大多數使用情況下都不是問題,但在測試中這樣一個緊密的循環中,您可能會達到這些限制並通過內聯驅逐緩存。

因此,爲了更好地瞭解發生了什麼,請查看調試中的Ehcache日誌並查看實際情況。 如果看到驅逐,則循環速度會更慢或者增加磁盤寫入隊列的某些設置,例如緩存元素上的diskSpoolBufferSizeMB屬性。

+0

謝謝!我認爲它不符合我的要求,因爲我無法控制數據放入ehcache的速度。我需要的是溢出模型,除非最低層(磁盤)已滿,否則不會丟失數據。 – abhi

0

面臨同樣的問題。在週期我加入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(項目),它的工作原理沒有問題。

版本2。6

這就是答案Ehcache set to eternal but forgets elements anyway?

相關問題