1

我正在使用 Guava 缓存保持并定期刷新我们从长时间运行的数据库查询中收集的一些统计信息。我目前看到的问题是所有线程都必须等待刷新,而不是让调用者获取过期的缓存值。番石榴缓存中有没有办法允许过时的读取?

缓存是这样构建的

 cache = CacheBuilder.<DateType, List<DataValueEventQuality>> newBuilder()
                .expireAfterWrite(cacheExpirySeconds, TimeUnit.SECONDS).build();

我使用从缓存中检索cache.get(key, Callable)

4

2 回答 2

1

看来您为此使用了错误的方法。从文档中LoadingCache有两种方法:

void put(K key, V value)

将值与此缓存中的键相关联。如果缓存先前包含与键关联的值,则旧值将替换为值。

这是原子的,缓存必须等待。

void refresh(K key)

为 key key 加载一个新值,可能是异步的。当新值正在加载之前的值(如果有)将继续由 get(key) 返回,除非它被驱逐

你没有说你正在使用什么样的缓存或显示任何代码,所以我不知道你是否使用LoadingCache. 但是您需要使用refresh缓存重新加载仍然允许读取旧值的值。

于 2013-07-26T09:53:39.900 回答
1

是的,我知道这很旧,但我今天想通了,所以这是答案:取自谷歌文档: https ://code.google.com/p/guava-libraries/wiki/CachesExplained#Refresh

关键部分是你想要 refreshAfterWrite 而不是 expireAfterWrite

// Some keys don't need refreshing, and we want refreshes to be done      asynchronously.
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
   .maximumSize(1000)
   .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 (neverNeedsRefresh(key)) {
             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;
           }
         }
       });
于 2015-09-09T22:10:12.390 回答