如何設(shè)計一個牛逼的本地緩存!
轉(zhuǎn)自:juejin.im/post/6844904003394863118
最近在看Mybatis的源碼,剛好看到緩存這一塊,Mybatis提供了一級緩存和二級緩存;一級緩存相對來說比較簡單,功能比較齊全的是二級緩存,基本上滿足了一個緩存該有的功能;當(dāng)然如果拿來和專門的緩存框架如ehcache來對比可能稍有差距;本文我們將來整理一下實現(xiàn)一個本地緩存都應(yīng)該需要考慮哪些東西。
考慮點
1.數(shù)據(jù)結(jié)構(gòu)
2.對象上限
3.清除策略
4.過期時間
5.線程安全
6.簡明的接口
7.是否持久化
8.阻塞機制
如何實現(xiàn)
1.數(shù)據(jù)結(jié)構(gòu)
????Map<Object,?Object>?cache?=?new?ConcurrentHashMap<Object,?Object>()Mybatis使用HashMap本身是非線程安全的,所以可以看到起內(nèi)部使用了一個SynchronizedCache用來包裝,保證線程的安全性;?
2.對象上限
3.清除策略
LRU?:Least Recently
Used的縮寫最近最少使用,移除最長時間不被使用的對象;常見的使用LinkedHashMap來實現(xiàn),也是很多本地緩存默認(rèn)使用的策略;?
FIFO?:先進先出,按對象進入緩存的順序來移除它們;常見使用隊列Queue來實現(xiàn);?
LFU?:Least Frequently
Used的縮寫大概也是最近最少使用的意思,和LRU有點像;區(qū)別點在LRU的淘汰規(guī)則是基于訪問時間,而LFU是基于訪問次數(shù)的;可以通過HashMap并且記錄訪問次數(shù)來實現(xiàn);?
SOFT?:軟引用基于垃圾回收器狀態(tài)和軟引用規(guī)則移除對象;常見使用SoftReference來實現(xiàn);?
WEAK?:弱引用更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則移除對象;常見使用WeakReference來實現(xiàn);
4.過期時間
被動刪除?:每次進行g(shù)et/put操作的時候都會檢查一下當(dāng)前key是否已經(jīng)過期,如果過期則刪除,類似如下代碼:
????if?(System.currentTimeMillis()?-?lastClear?>?clearInterval)?{
??????????clear();
????}
????
5.線程安全
?????public?synchronized?void?putObject(Object?key,?Object?object)?{
????????...省略...
??????}
??????@Override
??????public?synchronized?Object?getObject(Object?key)?{
????????...省略...
??????}
????
6.簡明的接口
????public?interface?Cache?{
??????String?getId();
??????void?putObject(Object?key,?Object?value);
??????Object?getObject(Object?key);
??????Object?removeObject(Object?key);
??????void?clear();
??????int?getSize();
??????ReadWriteLock?getReadWriteLock();
????}
????
????public?interface?Cache<K,?V>?{
??????V?getIfPresent(@CompatibleWith("K")?Object?key);
??????V?get(K?key,?Callable?extends?V>?loader)?throws?ExecutionException;
??????ImmutableMap?getAllPresent(Iterable>?keys) ;
??????void?put(K?key,?V?value);
??????void?putAll(Map?extends?K,???extends?V>?m);
??????void?invalidate(@CompatibleWith("K")?Object?key);
??????void?invalidateAll(Iterable>?keys);
??????void?invalidateAll();
??????long?size();
??????CacheStats?stats();
??????ConcurrentMap?asMap() ;
??????void?cleanUp();
????}
7.是否持久化
????diskPersistent="false"?//是否持久化磁盤緩存
8.阻塞機制
????public?class?Memoizerl<A,?V>?implements?Computable<A,?V>?{
????????private?final?Map>?cache?=?new?ConcurrentHashMap>();
????????private?final?Computable?c;
????????public?Memoizerl(Computable?c)?{
????????????this.c?=?c;
????????}
????????@Override
????????public?V?compute(A?arg)?throws?InterruptedException,?ExecutionException?{
????????????while?(true)?{
????????????????Future?f?=?cache.get(arg);
????????????????if?(f?==?null)?{
????????????????????Callable?eval?=?new?Callable ()?{
????????????????????????@Override
????????????????????????public?V?call()?throws?Exception?{
????????????????????????????return?c.compute(arg);
????????????????????????}
????????????????????};
????????????????????FutureTask?ft?=?new?FutureTask (eval);
????????????????????f?=?cache.putIfAbsent(arg,?ft);
????????????????????if?(f?==?null)?{
????????????????????????f?=?ft;
????????????????????????ft.run();
????????????????????}
????????????????????try?{
????????????????????????return?f.get();
????????????????????}?catch?(CancellationException?e)?{
????????????????????????cache.remove(arg,?f);
????????????????????}
????????????????}
????????????}
????????}
????}
總結(jié)
后臺回復(fù)?學(xué)習(xí)資料?領(lǐng)取學(xué)習(xí)視頻
如有收獲,點個在看,誠摯感謝
評論
圖片
表情
