1. 程式人生 > 程式設計 >Caffeine LoadingCache用法詳解

Caffeine LoadingCache用法詳解

作用

  1. 快取
  2. 非同步持續更新快取

構造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是惰性重新整理。