0

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

@Component
@EnableCaching
public class CacheConfig {

   @Bean
   public Caffeine defaultCacheConfig() {
       return Caffeine.newBuilder()
               .expireAfterWrite(12, TimeUnit.HOURS);
   }
}

我正在使用咖啡因缓存库。

4

2 回答 2

2

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

因此,就我的愿景而言,它可以通过以下方式发挥作用:

  • 设置一个 Scheduled Spring 服务并配置所需的 Cron。通过字段或构造函数自动连接 CacheManager 并设置 refreshCache() 以清除咖啡因管理器的所有缓存。我会留下一个代码示例,但不确定它是否 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。

于 2021-03-09T15:47:58.250 回答
2

咖啡因支持可变过期,其中条目的持续时间必须独立计算。如果你想让所有条目同时过期,你可以写,

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, V value, 
          long currentTime, long currentDuration) {
        return currentDuration;
      }
      public long expireAfterRead(K key, V value, 
          long currentTime, 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());
}
于 2021-03-09T16:15:04.490 回答