【问题标题】:Scheduled in-memory cache invalidation based on predicate基于谓词的计划内存缓存失效
【发布时间】:2018-07-15 11:56:34
【问题描述】:

我将List<CompletableFuture> 存储在Map

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

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

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

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

可能类似于番石榴的东西

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

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

【问题讨论】:

  • @pvpkiran 有很多 TTL 失效实现,我正在寻找基于一些谓词的失效。
  • 也许使用expireAfterAccess(30, TimeUnit.SECONDS) removalListener(removalListener) 然后在removalListener 检查条目是否仍然有效(未来未完成)并将其重新添加回缓存/映射。
  • 您可以使用 CompletableFuture.allOf(...) 在期货列表完成后驱逐条目。

标签: java spring multithreading caching guava


【解决方案1】:

我怀疑是否有基于 Guava 的解决方案。由于您没有特别要求“仅限 Guava”的解决方案,因此我想提供一个想法,如何使用 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 使用公共线程池作为计时器。

免责声明:我是 cache2k 的作者,所以我不能绝对肯定地说没有基于 Guava 的可能解决方案。

【讨论】:

  • 这仍然是一种解决方法,但是一个非常好的解决方法,它将查看 cache2k。谢谢@cruflex
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
相关资源
最近更新 更多