2017-09-24 217 views
0

我们依赖一个系统来提供往往经常关闭的信息。目前我们使用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 

无缓存下载失败,因为 '参考系统' 是不可用

回答

0

如果您需要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.load方法&那里你可以检查/从任何来源获得新的数据。

+0

time-to-live-seconds并不是我正在寻找的,正如我的问题描述的第一句中提到的那样。我不希望条目被盲目驱逐,我希望只有在有新版本可用时才能替换条目。 – Alexandru

+0

@Alexandru我刚刚使用'MapLoader'更新了我的答案,就像Guava CacheLoader一样,但有更多选项。 –