1 引言
作為java開發工作者,相信大家對于guava這個工具包都不會太陌生,而對于本地緩存技術guava cache,大家在日常的工作開發中也都有所了解,接下來本文就從各個角度入手來對于Google提供的guava cache進行解析。
2 guava cache應用場景
本地緩存的資料讀寫都在一個程序内,相對與redis等分布式緩存,不需要網絡傳輸的過程,通路速度很快,同時也受到JVM記憶體的制約,無法在資料量較多的場景下使用。
基于以上特點,guava cache的主要應用場景為以下幾種:
- 對于通路速度有較大要求
- 存儲的資料不經常變化
- 資料量不大,占用記憶體較小
- 需要通路整個集合
- 能夠容忍資料不是實時的
在這裡guava cache被用于儲存參數配置,也符合以上的應用場景條件。
3 guava cache的使用方式
guava cache位于com.google.common.cache包下,核心的類有兩個,一個是CacheBuilder,是用來建構緩存的,另一個是Cache,也就是緩存容器,用來存放緩存資料的。
要使用guava cache,首先要引入maven依賴:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
接下來寫一個簡單的示例:
Cache<String, String> localCache = CacheBuilder.newBuilder()
.initialCapacity(5)
.maximumSize(10)
.concurrencyLevel(3)
.expireAfterWrite(10, TimeUnit.SECONDS)
.build();
以上示例執行個體化了一個本地緩存,接下來介紹一下初始化的各項參數的含義:
initialCapacity:内部哈希表的最小容量,也就是cache的初始容量。
maximumSize:cache的最大緩存數。
concurrencyLevel:并發等級,也可以定義為同時操作緩存的線程數,由
可以看出,這個線程數預設為4。
expireAfterWrite:緩存寫入後重新整理時間。
從緩存中擷取資料調用的方法為get(K key, Callable<? extends V> loader)方法,此方法的含義是根據鍵key擷取資料,若key不存在,則通過執行指定的Callable方法來構造緩存,示例代碼如下所示:
Map<String, Dicdetail> dicDetailMap = ObLocateCache.locateConfigCache.get(key.toString(), new Callable<Map<String, Dicdetail>>() {
@Override
public Map<String, Dicdetail> call() throws Exception {
return getConfigParameterFromMaster(baseDomain, KeyConstants.WMS5_LOCATE_MANUAL);
}
});
從cache中删除資料分為被動删除和主動删除兩種:
1.被動删除:
- 基于資料大小删除:LRU+FIFO
- 基于過期時間删除:在指定時間内沒有被通路
- 基于引用删除:通過weakKeys和weakValues方法指定Cache隻儲存對緩存記錄key和value的弱引用。這樣當沒有其他強引用指向key和value時,key和value對象就會被垃圾回收器回收
2.主動删除:
//删除指定的key對應資料
cache.invalidate("s");
//将一批對應的資料删除
cache.invalidateAll(Arrays.asList("st","r","ing"));
//全部删除
cache.invalidateAll();
4 根據源碼分析guava cache的存儲原理
guava cache的資料結構跟ConcurrentHashMap類似,二者最基本的差別是ConcurrentMap會一直儲存所有添加的元素,直至将添加的元素移除。相對地,guava cache為了限制記憶體占用,通常都設定為自動回收元素。
guava cache的核心類為LocalCache,LocalCache實作了ConcurrentMap接口。其中有一個Segment數組,如下所示
擷取資料的方法源碼如下圖所示,可以看出guava cache的存儲原理為由Segment數組加上ReferenceEntry連結清單加上AtomicReferenceArray數組組成的資料結構。
資料結構圖如下所示:
Segement數組的長度決定了cache的并發數。每一個Segment都繼承了ReentrantLock,使用了單獨的鎖,對Segment的寫操作需要先拿到鎖。寫操作部分源碼如下所示:
5 總結
本文簡要叙述了guava cache的應用場景以及簡單的使用方式,通過源碼對于guava cache的存儲原理以及簡單的讀寫方法進行了介紹。相信通過閱讀本文,能夠對于常見的guava cache有一個大緻的認知。
作者:京東物流 王辰玮
來源:京東雲開發者社群 自猿其說Tech