【发布时间】:2018-03-05 10:22:09
【问题描述】:
我们依靠一个系统来提供经常出现故障的信息。目前我们使用 hazelcast 缓存条目,其过期策略为 1 小时。但是,这样做的问题是缓存条目被盲目驱逐,因此如果系统不可用,请求将失败一段时间。
我正在寻找一种方法来拦截 spring 的缓存以添加逻辑,松散地说我正在尝试从
修改内部 spring 调用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)决定何时驱逐条目,但只有在获得更新值的情况下才由应用程序决定。
我们可以处理数据稍微陈旧的风险,以获得更高的可用性。
编辑: 我想要一些行为类似于番石榴缓存构建器的 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
没有缓存获取失败,因为“参考系统”不可用
【问题讨论】:
标签: java spring spring-boot hazelcast spring-cache