Caffeine LoadingCache用法詳解
阿新 • • 發佈:2019-12-31
作用
- 快取
- 非同步持續更新快取
構造LoadingCache物件
LoadingCache<Integer,String> loadingCache = Caffeine.newBuilder()
.expireAfterWrite(1,TimeUnit.SECONDS)
.refreshAfterWrite(500,TimeUnit.MILLISECONDS)
.maximumSize(10) // 快取最大數量
.removalListener((RemovalListener<Integer,String>) (integer ,s,removalCause) -> {
System.out.println("key:" + integer + " value:" + s + " cause:"+removalCause);
})
.build(new CacheLoader<Integer,String>() {
@Nullable
@Override
public String load(@NonNull Integer i) throws Exception {
return i.toString();
}
@Override
public Map<Integer,String> loadAll(Iterable<? extends Integer> keys) {
Map<Integer,String> map = new HashMap<>();
for (Integer i : keys) {
map.put(i,i.toString());
}
return map;
}
});
複製程式碼
引數解析
- expireAfterWrite:失效策略,類似引數還有expireAfterAccess,key的快取時間到期以後並不會被立即刪除,caffeine使用惰性刪除的策略,在LoadingCache被修改,如新增,更新等,或者該失效的key被訪問的時候才會刪除。
- refreshAfterWrite:重新整理策略,設定為比寫入時間小可以保證快取永不失效,對於某些場景,比如請求頻率低但是耗時長的業務來說,自動重新整理能夠顯著提升效率和體驗
- maximumSize:快取的item的最大數目,如果超過這個數, caffeine將根據Window TinyLfu策略淘汰一些key,類似的引數還有maximumWeight,示例程式碼如下,設定maximumWeight的同時,要設定weigher引數,根據key生成對應的weight,如果累計weight達到了maximumWeight,將會進行key的淘汰,淘汰策略與maximumSize一樣,與weight無關。另外,maximumSize與maximumWeight不能同時使用,否則會報IllegalStateException。
LoadingCache<Integer,String> weightLoadingCache = Caffeine.newBuilder()
.maximumWeight(1000)
.weigher((Weigher<Integer,s) -> integer)
.build(new CacheLoader<Integer,String>() {
@Nullable
@Override
public String load(@NonNull Integer integer) throws Exception {
return null;
}
});
複製程式碼
- removalListener:當快取被移除的時候執行的策略,例如打日誌等
- build引數CacheLoader:用於refresh時load快取的策略,根據具體業務而定,建議在實現load方法的同時實現loadAll方法loadAll方法適用於批量查快取的需求,或者重新整理快取涉及到網路互動等耗時操作。比如你的快取資料需要從redis裡獲取,如果不實現loadAll,則需要多次load操作,也就需要多次redis互動,非常耗時,而實現loadAll,則可以在loadAll裡向redis傳送一條批量請求,顯著降低網路互動次數和時間,顯著提升效率。
注意事項
caffeine是不快取null值的,如果在load的時候返回null,caffeine將會把對應的key從快取中刪除,同時,loadAll返回的map裡是不可以包含value為null的資料,否則將會報NullPointerException
常用方法
V get(@NonNull K key)
返回給定的key在LoadingCache中的資料,如果cache中沒有該key,將呼叫CacheLoader的load方法去load資料,如果load不到資料,將返回null。
Map<K,V> getAll(@NonNull Iterable<? extends K> keys)
返回keys中的key的快取資料,組合成map,如果某個key或某些key在快取中不存在,將會呼叫loadAll去load資料,loadAll仍然無法load到資料的key,將不會put到返回的map裡。
void refresh(@NonNull K key)
明確地更新某個key,非同步呼叫load
put,putAll
這兩個方法明確地新增快取,對於LoadingCache來說,實際上是不需要呼叫,因為在get和getAll的時候會自動load快取,如果快取不存在。
問題
LoadingCache雖然定義了refreshAfterWrite,但是實際上,如果你一直不訪問某個快取,它是不會自動重新整理的,也就是說LoadingCache是惰性重新整理。