2011-03-07 4 views
2

最近、TerracottaでEHCacheを使用してアプリケーションデータの分散データキャッシュを実行し始めました。どんなクライアントノードもヒープのために約2GBを持っているのに対して、サーバノードは8GBを持っているとしましょう。 1日あたり約1.5GBのデータを生成します。Terracottaを使用するEHCacheは、分散ヒープからの退去をどのように処理しますか?

通常、特定のクライアントは特定の日のデータセット(約1.5GB)を使用しますが、サーバーは明らかにそのすべてを保持する必要があります。

有効期限を切る方法は、ヒープが大きくなったときのLRUベースです。したがって、特定のL1クライアントサイドキャッシュが大きすぎると(たとえば、day1からday2に切り替えると)、L1からすべてのday1データを削除すると思います。 6番目のデータセットを取得するときにL2が大きすぎると、最も古いデータセットが完全に期限切れになります。私はtime-to-liveやtime-to-idle値については何の意見も持っていないので、未設定のままにしておきます。

見て数日後、私はこれが私が期待しているように動作しているとは思わない。例えば、私はL2の最大要素数が4のテストを実行しました。これには4つの要素がありました。それから私は第五の要素を置くように行きました。 Cache.put()は例外なく返されましたが、同じキーを持つCache.get()の直後にnullが返されました。

私の質問は、どうすればEHCache + Terracottaに私が望む、あるいは少なくとも何かをすることができますか?

答えて

1

大雑把に言えば、不思議な振る舞いは、L1キャッシュがL2キャッシュの内容を知っているかどうかによって決まります。接続された単体テストはペアで実行されることを意図しており、ペアの各要素は別々のJVMで実行され、EHCacheの単一性を回避します。

よく動作するL1-> L2関係は、動作するべきだと思う方法は、エラーなしで.put()を実行すると、直後に同じキーのget()を実行できるはずです問題(他のスレッドが同時に実行されていないと仮定していない場合)。しかし、Terracotta EHCacheでは、.put()が追い出されなければならないものがあれば、追い出すことはできません。また、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()); 
    } 
} 
関連する問題