我正在使用具有以下配置的Caffeine缓存:
datesCache = Caffeine.newBuilder()
.maximumSize(1000L)
.expireAfterWrite(1, TimeUnit.HOURS)
.writer(new CacheWriter<String, Map<String, List<ZonedDateTime>>>() {
@Override
public void write(@NonNull final String key, @NonNull final Map<String, List<ZonedDateTime>> datesList) {
CompletableFuture.runAsync(() -> copyToDatabase(key, datesList), Executors.newCachedThreadPool());
}
@Override
public void delete(@NonNull final String key, @Nullable final Map<String, List<ZonedDateTime>> datesList,
@NonNull final RemovalCause removalCause) {
System.out.println("Cache key " + key + " got evicted from due to " + removalCause);
}
})
.scheduler(Scheduler.forScheduledExecutorService(Executors.newSingleThreadScheduledExecutor()))
.removalListener((key, dateList, removalCause) -> {
LOG.info("Refreshing cache key {}.", key);
restoreKeys(key);
})
.build();
如果值满足某些条件,则在写入高速缓存时,我正在使用CacheWriter
将记录复制到分布式数据库。另外,在驱逐后,我正在使用RemovalListener
来调用具有退出密钥的后端服务,以使记录保持最新。
为了完成这项工作,我还必须在启动服务时初始化缓存,并使用put
方法在缓存中插入值。我使用datesCache.get(key, datesList -> callBackendService(key))
从缓存中检索值,以防万一请求是初始化时没有得到的键。
利用此缓存的API的使用期很长,由于某些原因,似乎RemovalListener
和{{1}中的代码被逐出(在每个请求中)? }每隔几毫秒执行一次,最终创建了25,000个线程,并消除了服务错误。
有人可以告诉我我是否犯了致命的错误?还是显而易见的痛苦是错误的?我觉得我对咖啡因有误解。
目标是让缓存中的记录每1小时刷新一次,刷新后,从后端API获取新值,并在满足某些条件的情况下将其持久保存在数据库中。
答案 0 :(得分:0)
由于RemovalListener
是异步的,因此缓存进入了无限循环,因此,在重负载下,RemovalListener
之前,缓存值已被对过期密钥的请求所取代实际刷新缓存。
因此,这些值将:
REPLACED
删除原因将其从缓存中删除RemovalListener
解决方案:
评估RemovalCause
中的RemovalListener
以忽略REPLACED
键。可以使用方法wasEvicted()
或比较枚举值本身。