Caffeine Java缓存-如果refreshAfterWrite过期,如何先加载新值,然后返回新值而不是旧值

我正在尝试使用咖啡因缓存并遇到问题:

比方说,缓存为空,我查询一个值,它使用加载程序并将新值加载到缓存中,经过2天后,我查询相同的值,并得到 OLD 值首先,然后在单独的线程上启动刷新,并在可能的情况下加载新值。

caffeine.newBuilder()
        .refreshAfterWrite(5,TimeUnit.MINUTES)
        .expireAfterWrite(3,TimeUnit.DAYS)
        .build(loader);

我要存档的是-尝试先刷新并在可能的情况下先返回新值,如果出了问题,则仅返回旧值。我该如何存档?如何实现简单,面向未来的整洁实施,而又没有变通办法?太棒了!

编辑:此解决方案能否正常工作?

boolean needsSyncRefresh = cache.policy().expireAfterWrite()
                .flatMap(stringBigDecimalExpiration -> stringBigDecimalExpiration.ageOf(key))
                .filter(age -> age.toMinutes() < 0 || age.toMinutes() > REFRESH_AFTER_MINUTES)
                .isPresent();

V value = cache.get(key);

if (needsSyncRefresh) {
    return cache.asMap().computeIfPresent(key,(k,oldValue) -> {
        if (oldValue.equals(value)) {
            try {
                return loader(key);
            } catch (Exception e) {
                //handle error
            }
        }
        return oldValue;
    });
}
return value;
LIUYAOZU 回答:Caffeine Java缓存-如果refreshAfterWrite过期,如何先加载新值,然后返回新值而不是旧值

我认为这里不需要使用CacheWriter。而是检查元数据以确定是否需要刷新。

最简单的方法可能是运行计划的任务,以尽早触发刷新。例如,

var policy = cache.policy().expireAfterWrite().get();
for (var key : cache.asMap().keySet()) {
  boolean refresh = policy.ageOf(key)
      .filter(age -> age.toDays() >= 2)
      .isPresent();
  if (refresh) {
    cache.refresh(key);
  }
}

稍微复杂一点的版本会在检索时执行此操作,方法是检查检索到的值是否陈旧并执行新的计算,例如

V value = cache.get(key,this::loadValue);

var policy = cache.policy().expireAfterWrite().get();
boolean refresh = policy.ageOf(key)
    .filter(age -> age.toDays() >= 2)
    .isAbsent();
if (!refresh) {
  return value;
}
return cache.asMap().compute((key,oldValue) -> {
  if ((oldValue != null) && (oldValue != value)) {
    return oldValue; // reloaded by another thread
  }
  try {
    return loadValue(key);
  } catch (Exception e) {
    logger.error("Failed to load {}",key,e);
    return oldValue;
  }
});
本文链接:https://www.f2er.com/2551065.html

大家都在问