2017-09-24 219 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一樣,但有更多選項。 –