2016-04-21 3 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> 

Мои ожидания здесь есть, когда кэш заполнен до (то есть кэш размер превышает 50М), я хочу LRU элемент (ы), чтобы быть нажатой в файл и, следовательно, создавая пространство для нового элемента в памяти.

Однако это не так, как Ehcache работает, я сделал пробный тест, чтобы проверить количество элементов в кэше:

государственной статической силы основных (String [] арг) бросает исключение {

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 элементов в кеш (каждый элемент размера соответствует 4 МБ), я могу видеть только 7 элементов в кеше (ehCache.getSize() возвращает 7), а также я не вижу файл на диске растет.

Может ли кто-нибудь из экспертов EhCache помочь мне здесь, если мне что-то не хватает. Благодарю.

ответ

0

Во-первых, в отношении топологии Ehcache:

  • многоуровневая модель за Ehcache навязывает, так как, по крайней мере 2,6, что все отображения присутствуют в нижнем ярусе, диск в вашем случае, во все времена.

Это означает, что он больше не является моделью переполнения.

Теперь, почему ваш тест ведет себя иначе, чем то, что вы ожидаете:

  • Ehcache 2.x диск уровень оставляет ключи в памяти, и когда ваша куча память размера, объем пространства, занимаемый ключ вычитается из этой емкости.
  • Ehcache 2.x записывает асинхронно на диск и имеет ограниченные очереди для этого. Хотя это не проблема в большинстве случаев использования, в таком жестком цикле в тесте вы можете столкнуться с этими ограничениями и сбросить кеш, вытеснив inline.

Поэтому, чтобы лучше понять, что происходит, взгляните на журналы 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?