2012-10-05 21 views
5

永続的なDBに格納されているデータよりもメモリ内のキャッシュを維持することができます。Javaで周期的にリフレッシュするキャッシュを実装する

データを使用して、UIのエントリのリスト/マップにデータを入力します。任意の時点で、UIに表示されるデータは可能な限り更新されている必要があります(これはキャッシュのリフレッシュ頻度で行うことができます)。

通常のキャッシュ実装とこの特定のキャッシュとの主な違いは、定期的にすべての要素を一括リフレッシュする必要があるため、LRUキャッシュとはかなり異なる点です。

私はこの実装をJavaで行う必要があります。これを構築するために利用できる既存のフレームワークがあれば、それは素晴らしいことでしょう。

私はGoogle Guavaキャッシュライブラリを調べましたが、バルクリフレッシュではなくエントリごとのリフレッシュに適しています。キャッシュ全体をリフレッシュする簡単なAPIはありません。

ご協力いただければ幸いです。

また、リフレッシュを段階的に行うことができる場合は、キャッシュ全体をリフレッシュする際に発生する唯一の制限は、キャッシュのサイズが非常に大きい場合、メモリヒープが少なくとも2回新しいエントリをロードして古いマップを新しいマップに置き換えるためにキャッシュのサイズキャッシュがインクリメンタルであるか、またはチャンクされたリフレッシュ(等しいサイズでリフレッシュ)が行われている場合は、それが素晴らしいでしょう。

答えて

3

EHCacheを取得したいとloadDataFromDBとにupdateDataを実装するには、かなりフル機能を備えたJavaのキャッシュライブラリです。私は彼らにあなたのために働く何かがあると思います。

キャッシュの増分リロード(ほとんどのキャッシュで動作する)を実行するには、現在ロードされているエントリを繰り返し実行して強制的にリフレッシュします。 (このタスクはバックグラウンドスケジューラで実行できます)。

キャッシュ全体を強制的にリロードする代わりに、EHCacheにはエントリの「生存時間」を指定できるため、エントリが古すぎる場合は自動的にリロードされます。

+1

@ jtahlborn - EhCacheのBulkLoader API(http://ehcache.org/documentation/apis/bulk-loading)は有用ですが、refreshTimeまたは定期的な間隔の時間オプションを提供していれば素晴らしいでしょうキャッシュリフレッシュのスケジューリングとにかく、いつでも外部スケジューラを使用してバルクロードAPIを定期的に呼び出すことで実現できます。答えをありがとう。 –

+0

EHCacheについては、http://www.ehcache.org/documentation/3.3/thread-pools.htmlおよびhttp://terracotta.org/documentation/4.1/bigmemorymax/api/bulk-loading – Aliuk

+0

をご覧ください。 time-to-liveは単にキャッシュから要素を削除するだけではありませんか?ここで書いたものと同じではありません。 "自動リロード" – javagirl

0

ただ、このクラスを継承し、あなたがincrementialアップデートに

import org.apache.log4j.Logger; 
import java.util.List; 
import java.util.concurrent.Semaphore; 


public abstract class Updatable<T> 
{ 
    protected volatile long lastRefreshed = 0; 
    private final int REFRESH_FREQUENCY_MILLISECONDS = 300000; // 5 minutes 
    private Thread updateThread; 
    private final Semaphore updateInProgress = new Semaphore(1); 

    protected static final Logger log = Logger.getLogger(Updatable.class); 

    public void forceRefresh() 
    { 
     try 
     { 
      updateInProgress.acquire(); 
     } 
     catch (InterruptedException e) 
     { 
      log.warn("forceRefresh Interrupted"); 
     } 

     try 
     { 
      loadAllData(); 
     } 
     catch (Exception e) 
     { 
      log.error("Exception while updating data from DB", e); 
     } 
     finally 
      { 
      updateInProgress.release(); 
     } 

    } 

    protected void checkRefresh() 
    { 
     if (lastRefreshed + REFRESH_FREQUENCY_MILLISECONDS <  System.currentTimeMillis()) 
      startUpdateThread(); 
    } 

    private void startUpdateThread() 
    { 
     if (updateInProgress.tryAcquire()) 
     { 
      updateThread = new Thread(new Runnable() 
      { 
       public void run() 
       { 
        try 
        { 
         loadAllData(); 
        } 
        catch (Exception e) 
        { 
         log.error("Exception while updating data from DB", e); 
        } 
        finally 
        { 
         updateInProgress.release(); 
        } 
       } 
      }); 

      updateThread.start(); 
     } 
    } 

    /** 
    * implement this function to load the data from DB 
    * 
    * @return 
    */ 
    protected abstract List<T> loadFromDB(); 

    /** 
    * Implement this function to hotswap the data in memory after it was loaded from DB 
    * 
    * @param data 
    */ 
    protected abstract void updateData(List<T> data); 

    private void loadAllData() 
    { 
     List<T> l = loadFromDB(); 
     updateData(l); 
     lastRefreshed = System.currentTimeMillis(); 
    } 

    public void invalidateCache() 
    { 
     lastRefreshed = 0; 
    } 

} 
+0

回答RAに感謝します。 checkRefresh()関数が呼び出されるのはいつですか?私が正しく理解していれば、定期的にcheckRefreshを使ってポーリングするための連続した実行プロセスが必要です。私は、キャッシュローダーを使って新しいキャッシュをプラグインできるだけの、より洗練された実装を楽しみにしていました。 –

+0

クラスに実装するすべてのget操作でCheckRefreshを呼び出す必要があります。私。E:publicデータget(){checkRefresh(); //データを返す。 } –

+0

しかし、これは、更新スレッドがcronのように先読みされ、すでにデータをプリフェッチしたような場合に、そのようなケースが発生しなかった場合のデータ取得の待ち時間に影響します。 –

0

定期的なリフレッシングが必要ですか?キャッシュからデータを取得すると、リフレッシュロジックを適用できます。これにより、非同期リフレッシュが不要になり、キャッシュの古いコピーを維持する必要がなくなります。このIMOは、追加のオーバーヘッドが発生しないため、キャッシュデータを最新の状態に更新する最も簡単で最適な方法です。

T getData(){ 
     // check if the last access time + refresh interval >= currenttime if so then refresh cache 
    // return data 
    } 

これにより、リフレッシュ間隔に基づいてデータがリフレッシュされ、非同期リフレッシュが不要になります。

関連する問題