【问题标题】:Spring Cache interceptorSpring 缓存拦截器
【发布时间】: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


    【解决方案1】:

    如果你需要 refreshAfterWrite 来使用 Hazelcast,那就是 time-to-live-seconds

    time-to-live-seconds只有在你做map.put操作时才会改变,所以和Guava的refreshAfterWrite设置基本相同。

    请看:http://docs.hazelcast.org/docs/3.8.6/manual/html-single/index.html#map-eviction

    此外,您很可能希望在过期后刷新缓存中的数据。然后就可以使用MapLoader或者接口了。 (http://docs.hazelcast.org/docs/3.8.6/manual/html-single/index.html#loading-and-storing-persistent-data)

    这样,当数据过期时,下一次调用将点击MapLoader.loadmethod,您可以从任何来源检查/获取新数据。

    【讨论】:

    • time-to-live-seconds 不是我在问题描述的第一句话中提到的。我不想盲目地驱逐条目,我希望只有在有新版本可用时才替换它们。
    • @Alexandru 我刚刚用MapLoader 更新了我的答案,它类似于 Guava CacheLoader,但有更多选项。
    猜你喜欢
    • 2018-08-09
    • 2010-09-10
    • 1970-01-01
    • 2014-05-19
    • 2017-02-25
    • 1970-01-01
    • 2016-10-23
    • 2015-10-21
    • 2019-04-27
    相关资源
    最近更新 更多