我们依赖一个系统来提供往往经常关闭的信息。目前我们使用hazelcast缓存1小时到期策略的条目。但是,这有一个问题,即缓存条目被盲目驱逐,因此如果系统不可用,请求将会失败一段时间。Spring Cache拦截器
我正在寻找一种方式来拦截春天的缓存添加逻辑,严格意义上,我试图从
Object valueFromCache = cache.getValue(cacheKey);
if (null == valueFromCache) {
valueFromCache = cachedMethod.invokeMethod();
cache.putValue(cacheKey, valueFromCache);
}
return valueFromCache;
修改内部弹簧调用到
Object valueFromCache = cache.getValue(cacheKey);
if (null == valueFromCache) {
valueFromCache = cachedMethod.invokeMethod();
cache.putValue(cacheKey, valueFromCache);
} else if (isValueExpired(valueFromCache)) {
try {
valueFromCache = cacheMethod.invokeMethod();
cache.putValue(cacheKey, valueFromCache);
} catch (FailedToRefreshDataException ex) {
doWhateverWithException(ex);
}
}
return valueFromCache;
基本上,我不想让底层缓存提供者(在我的例子中为hazelcast)决定何时驱逐条目,但只有在获取新值时才应用该应用。
我们可以处理稍微陈旧的数据以获得更高可用性的风险。
编辑: 我想要的东西,功能类似于番石榴cachebuilder的refreshAfterWrite
例如
public static void main(String[] args) throws ExecutionException, InterruptedException {
AtomicInteger atomicInteger = new AtomicInteger();
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(100, MILLISECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String value) throws Exception {
int intValue = atomicInteger.incrementAndGet();
if (intValue % 2 == 0) {
throw new IllegalStateException("Failed to whatever");
}
return value + intValue;
}
});
for (int i = 0; i < 10; i++) {
System.out.println("Attempt " + i + "=" + cache.get("Shoes"));
Thread.sleep(50);
}
}
输出
Attempt 0=Shoes1
Attempt 1=Shoes1
Attempt 2=Shoes1
Attempt 3=Shoes3
Attempt 4=Shoes3
Attempt 5=Shoes3
Attempt 6=Shoes5
Attempt 7=Shoes5
Attempt 8=Shoes5
Attempt 9=Shoes7
无缓存下载失败,因为 '参考系统' 是不可用
time-to-live-seconds并不是我正在寻找的,正如我的问题描述的第一句中提到的那样。我不希望条目被盲目驱逐,我希望只有在有新版本可用时才能替换条目。 – Alexandru
@Alexandru我刚刚使用'MapLoader'更新了我的答案,就像Guava CacheLoader一样,但有更多选项。 –