web-dev-qa-db-ja.com

Google Guavaを使用してキャッシュを自動的に更新する方法は?

キャッシュにGoogle Guavaライブラリを使用しています。自動キャッシュ更新の場合、次のように実行できます。

cache = CacheBuilder.newBuilder()               
                    .refreshAfterWrite(15, TimeUnit.MINUTES)
                    .maximumSize(100)
                    .build(....);

ただし、エントリの最初の古いリクエストが発生したときに自動更新が実行されます

キャッシュデータに対する要求がなくても自動的に更新する方法はありますか?キャッシュデータが呼び出されたかどうかにかかわらず、15分ごとにDbからキャッシュデータを取得して読み込む必要があります。

また、Guavaのキャッシュの有効期限はキャッシュ全体です。 キーに基づいてキャッシュ値を期限切れにすることは可能ですか?キー「NOT_SO_FREQ_CHANGE_DATA」のキャッシュデータは1時間ごとに期限切れになり、キー「FREQ_CHANGING_DATA」のデータは15分ごとに期限切れになりますか?

30

Guavaにはキャッシュを一括で更新する方法はありませんが、定期的な更新を自分でスケジュールできます。

_LoadingCache<K, V> cache = CacheBuilder.newBuilder()
        .refreshAfterWrite(15, TimeUnit.MINUTES)
        .maximumSize(100)
        .build(new MyCacheLoader());

for (K key : cache.asMap().keySet()) {
    cache.refresh(key);
}
_

ただし、その場合は、MyCacheLoaderCacheLoader.reload(K, V)メソッドをオーバーライドして、非同期に実行することができます。

2番目の質問については、いいえ、グアバではエントリごとの有効期限を設定できません。

26
Frank Pavageau

パラレルストリームを使用するJava 8バージョン:

Executors
        .newSingleThreadScheduledExecutor()
        .scheduleWithFixedDelay(() -> configurationCache
                .asMap()
                .keySet()
                .parallelStream()
                .forEach((key) -> configurationCache.refresh(key)),
            0,
            1, TimeUnit.SECONDS);
6

最初の質問。定期実行を開始するには、スケジュールされたエグゼキューターを使用します。

2番目の質問。キャッシュキーまたは以前にキャッシュされた値から有効期限ポリシーを推測できる場合、さまざまな間隔でデータを更新できます。

これに基づいて: https://code.google.com/p/guava-libraries/wiki/CachesExplained#Refresh

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
   .refreshAfterWrite(1, TimeUnit.MINUTES)
   .build(
       new CacheLoader<Key, Graph>() {
         public Graph load(Key key) { // no checked exception
           return getGraphFromDatabase(key);
         }

         public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
           if (!needsRefresh(key,prevGraph)) {
             return Futures.immediateFuture(prevGraph);
           } else {
             // asynchronous!
             ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
               public Graph call() {
                 return getGraphFromDatabase(key);
               }
             });
             executor.execute(task);
             return task;
           }
         }
       });

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleWithFixedDelay(
    new Runnable() {
        public void run() {
            for (Key key : graphs.asMap().keySet()) {
                graphs.refresh(key);
            }
        }
    }, 0, UPDATE_INTERVAL, TimeUnit.MINUTES);
6
McKidoubled