2011-03-07 2 views
2

최근 Terracotta와 함께 EHCache를 사용하여 응용 프로그램 데이터에 대한 분산 데이터 캐시를 실행하기 시작했습니다. 서버 노드가 8GB 인 반면 클라이언트 노드는 힙에 대해 약 2GB를 가지고 있다고 가정 해 봅시다. 우리는 하루에 약 1.5GB의 많은 데이터를 생성합니다.테라코타를 사용하는 EHCache는 분산 힙에서 퇴거를 어떻게 처리합니까?

일반적으로 모든 클라이언트는 특정 날짜의 데이터 집합 (약 1.5GB)을 사용하지만 서버는 분명히 모든 데이터를 보유해야합니다.

만료가 작동하도록하는 방법은 힙이 커질 때 LRU를 기준으로합니다. 따라서 특정 L1 클라이언트 측 캐시가 너무 커지면 (예 : day1에서 day2로 전환하면) L1에서 모든 day1 데이터를 제거 할 것으로 예상됩니다. 6 번째 데이터 세트를 얻을 때 L2가 너무 커지면 가장 오래된 데이터 세트가 완전히 만료됩니다. 나는 time-to-live 또는 time-to-idle 값에 대해 어떤 의견도 갖고 있지 않다. 그래서 나는 그것들을 설정하지 않은 상태로 둘 것이다.

며칠 후, 예상대로 작동하지 않는다고 생각합니다. 예를 들어, 나는 L2 max 요소가 4 인 테스트를 실행했습니다. 4 개의 요소로 채웠습니다. 그런 다음 다섯 번째 요소를 추가했습니다. Cache.put()은 예외없이 반환되었지만 같은 키를 가진 바로 다음에있는 Cache.get()은 null을 반환했습니다!

제 질문은 EHCache + Terracotta에서 원하는 것을, 또는 적어도 가까운 것을 어떻게 할 수 있습니까?

답변

1

많은 엉망이 된 후에, L1 캐시가 L2 캐시에 무엇이 있는지에 대한 지식이 있는지 여부에 따라 신비한 행동이 결정됩니다. 첨부 된 단위 테스트는 쌍으로 실행될 예정이며 쌍의 각 요소는 EHCache 단일성을 피하기 위해 별도의 JVM에서 실행됩니다.

잘 작동하는 L1-> L2 관계가 작동해야한다고 생각하는 방식은 오류없이 .put()을 수행하면 바로 뒤에 동일한 키의 get()을 수행 할 수 있어야한다는 것입니다 문제 (다른 동시 실행중인 스레드가 물건을 망칠 필요가 없다고 가정). 그러나 Terracotta EHCache에서 .put()이 제거되도록해야하는 경우 퇴출 될 수있는 키에 대해 L1 클라이언트가 '알고있는'경우를 제외하고는 put()이 자동으로 무시됩니다. * 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()); 
    } 
} 
관련 문제