是否有咖啡因功能可以在定义的时间后从缓存中清除特定项目并同时重新创建它?

问题描述

ExpireAfter 只会清除该项目,但不会重新创建该项目。所以我需要做的是,在预定义的时间间隔之后,我需要从缓存中清除特定项目,同时我需要重新创建它。如果数据没有变化,它可能会使用相同的数据重新创建。假设数据被改变,重新创建将给出最新的对象。

我的想法是一直从缓存中检索最新的项目。相比之下,刷新功能 (https://github.com/ben-manes/caffeine/wiki/Refresh) 将为第一个请求提供陈旧的项目并执行异步加载。因此,对于第二个请求,缓存将提供最新的对象。

  • 重新获取过期条目的异步删除侦听器 应该在我的情况下工作。你能给我提供一些信息吗 如何实现这一目标?
  • 我也很想知道计划任务是如何做到的?

假设缓存可以解决以下两种情况:

后续请求案例:

  • 我知道 refreshAfterWrite 将提供陈旧的条目 第一次但对于第二次请求,如果缓存会发生什么 尚未完成加载过期条目?

  • 缓存是否阻塞第二个请求,完成重新获取,并且 然后为第二个请求提供最新值?。

  • 这个想法是让缓存提供最新的数据 定义条目到期时间。

如果缓存必须一次性加载与其容量相等的值:

  • 假设缓存大小为 100 并且加载所有 100 个项目的时间 是 2 分钟。

  • 假设第一个请求将加载 100 个项目到缓存中 同时,在定义的到期时间之后,缓存应该被驱逐并 重新获取所有 100 个元素。

  • 对于访问这 100 个项目中的项目的第二个请求,如何 我使缓存足够智能,以便它返回的条目 是否已重新加载并异步重新加载其他条目?。

  • 这个想法不是阻止对现有条目的任何请求。服务于 请求现有条目并为剩余条目重新加载 过期条目。

解决方法

重新获取过期条目的异步删除侦听器应该适用于我的情况。您能否提供一些有关如何实现这一目标的信息?

移除侦听器需要对缓存的引用,但在构建期间不可用。如果它改为调用私有方法,则不会捕获未初始化的字段,并且可以在运行时解析它。

Cache<K,V> cache = Caffeine.newBuilder()
    .expireAfterWrite(1,TimeUnit.HOURS)
    .removalListener((K key,V value,RemovalCause cause) -> {
      if (cause == RemovalCause.EXPIRED) {
        reload(key);
      }
    }).build();

private void reload(K key) {
  cache.get(key,k -> /* load */);
}

我也很想知道定时任务是怎么做的?

如果您正在重新加载所有条目,那么您甚至可能不需要键值缓存。在这种情况下,最简单的方法是重新加载一个不可变的地图。

volatile ImmutableMap<K,V> data = load();

scheduledExecutorService.scheduleAtFixedRate(() -> data = load(),/* initial */ 1,/* period */ 1,TimeUnit.HOURS);

我知道 refreshAfterWrite 将第一次提供过时条目,但对于第二次请求,如果缓存尚未完成加载过期条目会发生什么?

后续请求将获取陈旧条目,直到 (a) 刷新完成并更新映射或 (b) 条目被删除并且调用者必须重新加载。如果在刷新过程中条目过期,则可能发生 (b) 的情况,此时不再可以选择返回旧值。

缓存是否会阻塞第二个请求,完成重新获取,然后将最新值提供给第二个请求?。

不,会返回陈旧但有效的值。这是为了让刷新隐藏重新加载流行条目的延迟。例如,所有请求使用的应用程序配置在过期时会阻塞,从而导致周期性延迟。刷新会提前触发,重新加载,调用者永远不会发现它不存在。这会隐藏延迟,同时也允许空闲条目过期和消失。

如果缓存必须一次性加载与其容量相等的值……在定义的到期时间之后,缓存应逐出并重新获取所有 100 个元素。

您描述中不清楚的部分是缓存是否仅重新加载刷新周期内正在访问的条目,或者是否重新加载整个内容。前者是 Caffeine 提供的,而后者最好使用显式调度线程。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...