我可以像 CRON 作业一样安排 Java Spring Cache 在每小时结束时到期吗?

问题描述

我目前已将其设置为在 12 小时后过期。但是,它也会在每个缓存首次写入后 12 小时过期。我希望它仅在上午 12 点和下午 12 点刷新。这可能吗?在我的 cacheConfig 文件中,我有

i =0

我正在使用 caffeine Cache 库。

解决方法

我相信 Caffeine 不支持这种调度。但是,如果这是强烈要求并且应该按如下方式实现 - 您可以使用 Spring 的 @Scheduled 批注,它允许使用 Cron 配置。您可以在此处阅读相关内容:https://www.baeldung.com/spring-scheduled-tasks

因此,对于我的愿景,它可以按以下方式工作:

  • 设置预定的 Spring 服务并配置所需的 Cron。通过字段或构造函数自动装配 CacheManager 并设置 refreshCache() 以清除 Caffeine 管理器的所有缓存。我会留下一个代码示例,但不确定它是否 100% 有效:)

      @Component
      public class CacheRefreshService {
    
         @Autowired
         private CacheManager cacheManager;
    
         @Scheduled(cron = ...)
         public void refreshCache() {
            cacheManager.getCacheNames().stream()
               .map(CacheManager::getCache)
               .filter(Objects::nonNull)
               .forEach(cache -> cache.clear());
         }
     }
    

并且不要忘记为您的@Configuration-s 放置@EnableScheduling,或者如果您正在运行,您可以将其添加到@SpringBootApplication 中。

,

Caffeine 支持可变过期时间,其中条目的持续时间必须独立计算。如果您希望所有条目同时过期,您可以这样写,

Caffeine.newBuilder()
    .expireAfter(new Expiry<K,V>() {
      public long expireAfterCreate(K key,V value,long currentTime) {
        var toMidnight = Duration.between(LocalDate.now(),LocalDate.now().plusDays(1).atStartOfDay());
        var toNoon = Duration.between(LocalTime.now(),LocalTime.NOON);
        return toNoon.isNegative() ? toMidnight.toNanos() : toNoon.toNanos();
      }
      public long expireAfterUpdate(K key,long currentTime,long currentDuration) {
        return currentDuration;
      }
      public long expireAfterRead(K key,long currentDuration) {
        return currentDuration;
      }
    }).build();

对于这样一个简单的任务,使用过期可能是过度的。相反,如果您想清除缓存,则可以按照 @alexzander-zharkov 的建议,使用计划任务来代替。

@Scheduled(cron = "0 0,12 * * *")
public void clear() {
  cache.invalidateAll();
}

由于这会清空缓存,因此会在重新加载条目时造成性能损失。相反,您可以异步刷新缓存,以便重新加载条目而不会惩罚任何调用者。

@Scheduled(cron = "0 0,12 * * *")
public void refresh() {
  cache.refreshAll(cache.asMap().keySet());
}

相关问答

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