Как автоматически обновлять кеш с помощью Google Guava? - программирование
Подтвердить что ты не робот

Как автоматически обновлять кеш с помощью 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 минут?

4b9b3361

Ответ 1

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);
}

Но в этом случае вы можете переопределить метод CacheLoader.reload(K, V) в MyCacheLoader чтобы он выполнялся асинхронно.

Что касается второго вопроса, нет, вы не можете установить срок действия для каждой записи в Гуаве.

Ответ 2

1-й вопрос Используйте запланированного исполнителя, чтобы начать периодическое обновление.

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);

Ответ 3

версия JAVA 8 с параллельным потоком:

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

Ответ 4

Вот пример кода для обновления кеша. Кэш Guava легко реализовать, а также быстро.

import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class GuavaTest {
    private static GuavaTest INSTANCE = new GuavaTest();

    public static GuavaTest getInstance(){
        return INSTANCE;
    }   

    private LoadingCache<String,String> cache;

    private GuavaTest() {
        cache = CacheBuilder.newBuilder()
                .refreshAfterWrite(2,TimeUnit.SECONDS)
                .build(new CacheLoader<String, String>() {
                        @Override
                        public String load(String arg0) throws Exception {
                            return addCache(arg0);
                        }
                });
    }

    private String addCache(String arg0) {
        System.out.println("Adding Cache");
        return arg0.toUpperCase();
    }

    public String getEntry(String args) throws ExecutionException{
        System.out.println(cache.size());
        return cache.get(args);
    }

    public static void main(String[] args) {
        GuavaTest gt = GuavaTest.getInstance();
        try {
            System.out.println(gt.getEntry("java"));
            System.out.println(gt.getEntry("java"));
            Thread.sleep(2100);
            System.out.println(gt.getEntry("java"));
            System.out.println(gt.getEntry("java"));
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Я ссылался на эту статью пример кэширования guava