我可以像 CRON 作业一样安排 Java Spring 缓存在每个小时的顶部过期吗?
Can I schedule Java Spring Cache to expire at the top of each hour like a CRON job?
我目前将其设置为 12 小时后过期。但是,它也会在每个缓存首次写入后 12 小时过期。我希望它只在中午 12 点和中午 12 点刷新。这可能吗?在我的 cacheConfig 文件中,我有:
@Component
@EnableCaching
public class CacheConfig {
@Bean
public Caffeine defaultCacheConfig() {
return Caffeine.newBuilder()
.expireAfterWrite(12, TimeUnit.HOURS);
}
}
我正在使用咖啡因缓存库。
我相信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, 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());
}
我目前将其设置为 12 小时后过期。但是,它也会在每个缓存首次写入后 12 小时过期。我希望它只在中午 12 点和中午 12 点刷新。这可能吗?在我的 cacheConfig 文件中,我有:
@Component
@EnableCaching
public class CacheConfig {
@Bean
public Caffeine defaultCacheConfig() {
return Caffeine.newBuilder()
.expireAfterWrite(12, TimeUnit.HOURS);
}
}
我正在使用咖啡因缓存库。
我相信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, 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());
}