基于谓词计划的内存缓存失效

时间:2018-02-05 15:22:08

标签: java spring multithreading caching guava

List<CompletableFuture>存储了Map

 private final Map<UUID, List<CompletableFuture>> hydrationProcesses = new ConcurrentHashMap<>();

目前有一个守护程序线程每隔30秒运行一次,并删除已经完成的所有Futures

有很多TTL失效实现,我正在寻找基于某些谓词的失效。我想摆脱这个守护程序线程。

是否存在基于某些自定义逻辑的计划缓存失效的开箱即用解决方案。也许我错过了Spring / Guava中的某些东西?

也许与Guava的相似之处

CacheBuilder.newBuilder()
  .expireAfterAccess(2,TimeUnit.MILLISECONDS)
  .build(loader);

而是在访问后将所有内容标记为已过期我需要检查此Future是否已经完成,然后将其从缓存中删除。

1 个答案:

答案 0 :(得分:1)

我怀疑有基于番石榴的解决方案。由于您没有特别要求“仅限番石榴”的解决方案,因此我想了解如何使用cache2k来解决问题。

以下是设置的外观:

final long RECHECK_INTERVAL_MILLIS = 30000;
Cache<UUID, CompletableFuture<Void>> cache =
  new Cache2kBuilder<UUID, CompletableFuture<Void>>(){}
    .loader(new AdvancedCacheLoader<UUID, CompletableFuture<Void>>() {
      @Override
      public CompletableFuture<Void> load(UUID key,
                                          long currentTime,
                                          CacheEntry<UUID, CompletableFuture<Void>> currentEntry) {
        return currentEntry != null ? currentEntry.getValue() : null;
      }
    })
    .expiryPolicy(new ExpiryPolicy<UUID, CompletableFuture<Void>>() {
      @Override
      public long calculateExpiryTime(UUID key,
                                      CompletableFuture<Void> value,
                                      long loadTime,
                                      CacheEntry<UUID, CompletableFuture<Void>> oldEntry) {
        return value.isDone() ? NOW : loadTime + RECHECK_INTERVAL_MILLIS;
      }
    })
    .refreshAhead(true)
    .build();

实际上,cache2k具有与Guava或其他缓存类似的功能。然而,有一些微小的扩展,允许更复杂的设置。

这里使用的技巧是在读取操作中配置缓存,但使加载器返回当前缓存值。当条目到期时,由于refreshAhead(true)而调用加载器,但保留当前值并再次评估到期策略。您希望检查的谓词将进入到期政策。

其他缓存也已经过读取和自定义过期,但缺少“智能加载器”(AdvancedCacheLoader)的概念,它可以根据现有缓存值更有效地运行。

我们在制作中使用与此相似的设置。

也存在不利因素。如果使用自定义过期,则cache2k每个缓存使用一个计时线程。这意味着你的额外线程不会消失。将来会增强cache2k,以便在所有缓存之间共享一组全局时序线程。

免责声明:我是cache2k的作者,所以我绝对不能确定没有基于番石榴的可能解决方案。