Guava Cache簡介

緩存類型

  1. JVM 緩存
    首先是 JVM 緩存拗踢,也可以認為是堆緩存亲善。其實就是創(chuàng)建一些全局變量傲宜,如 Map、List 之類的容器用于存放數(shù)據(jù)侦铜。這樣的優(yōu)勢是使用簡單但是也有以下問題:
    • 只能顯式的寫入专甩,清除數(shù)據(jù)。
    • 不能按照一定的規(guī)則淘汰數(shù)據(jù)钉稍,如 LRU涤躲,LFU,F(xiàn)IFO 等贡未。
    • 清除數(shù)據(jù)時的回調(diào)通知种樱。
    • 其他一些定制功能等。
  2. Ehcache俊卤、Guava Cache
    所以出現(xiàn)了一些專門用作 JVM 緩存的開源工具出現(xiàn)了嫩挤,如本文提到的 Guava Cache。
    它具有上文 JVM 緩存不具有的功能消恍,如自動清除數(shù)據(jù)岂昭、多種清除算法、清除回調(diào)等狠怨。
    但也正因為有了這些功能佩抹,這樣的緩存必然會多出許多東西需要額外維護,自然也就增加了系統(tǒng)的消耗取董。
  3. 分布式緩存
    剛才提到的兩種緩存其實都是堆內(nèi)緩存,只能在單個節(jié)點中使用无宿,這樣在分布式場景下就招架不住了茵汰。
    于是也有了一些緩存中間件,如 Redis孽鸡、Memcached蹂午,在分布式環(huán)境下可以共享內(nèi)存栏豺。具體不在本次的討論范圍。
    final static Cache<Integer, String> cache = CacheBuilder.newBuilder()
            //設(shè)置cache的初始大小為10豆胸,要合理設(shè)置該值
            .initialCapacity(10)
            //設(shè)置并發(fā)數(shù)為5奥洼,即同一時間最多只能有5個線程往cache執(zhí)行寫入操作
            .concurrencyLevel(5)
            //設(shè)置cache中的數(shù)據(jù)在寫入之后的存活時間為10秒
            .expireAfterWrite(10, TimeUnit.SECONDS)
            //構(gòu)建cache實例
            .build();

清除緩存的策略

任何Cache的容量都是有限的,而緩存清除策略就是決定數(shù)據(jù)在什么時候應(yīng)該被清理掉晚胡。GuavaCache提了以下幾種清除策略:

  1. 基于存活時間的清除(Timed Eviction)
    這應(yīng)該是最常用的清除策略灵奖,在構(gòu)建Cache實例的時候,CacheBuilder提供兩種基于存活時間的構(gòu)建方法:
  • expireAfterAccess(long, TimeUnit):緩存項在創(chuàng)建后估盘,在給定時間內(nèi)沒有被讀/寫訪問瓷患,則清除。
  • expireAfterWrite(long, TimeUnit):緩存項在創(chuàng)建后遣妥,在給定時間內(nèi)沒有被寫訪問(創(chuàng)建或覆蓋)擅编,則清除。expireAfterWrite()方法有些類似于redis中的expire命令箫踩,但顯然它只能設(shè)置所有緩存都具有相同的存活時間爱态。若遇到一些緩存數(shù)據(jù)的存活時間為1分鐘,一些為5分鐘境钟,那只能構(gòu)建兩個Cache實例了锦担。
  1. 基于容量的清除(size-based eviction)
  • 在構(gòu)建Cache實例的時候,通過CacheBuilder.maximumSize(long)方法可以設(shè)置Cache的最大容量數(shù)吱韭,當緩存數(shù)量達到或接近該最大值時吆豹,Cache將清除掉那些最近最少使用的緩存。
  • 以上是這種方式是以緩存的“數(shù)量”作為容量的計算方式理盆,還有另外一種基于“權(quán)重”的計算方式痘煤。比如每一項緩存所占據(jù)的內(nèi)存空間大小都不一樣,可以看作它們有不同的“權(quán)重”(weights)猿规。你可以使用CacheBuilder.weigher(Weigher)指定一個權(quán)重函數(shù)衷快,并且用CacheBuilder.maximumWeight(long)指定最大總重。
  1. 顯式清除
    任何時候姨俩,你都可以顯式地清除緩存項蘸拔,而不是等到它被回收,Cache接口提供了如下API:
  • 個別清除:Cache.invalidate(key)
  • 批量清除:Cache.invalidateAll(keys)
  • 清除所有緩存項:Cache.invalidateAll()

基于引用的清除(Reference-based Eviction)

在構(gòu)建Cache實例過程中环葵,通過設(shè)置使用弱引用的鍵调窍、或弱引用的值、或軟引用的值张遭,從而使JVM在GC時順帶實現(xiàn)緩存的清除邓萨,不過一般不輕易使用這個特性。

  • CacheBuilder.weakKeys():使用弱引用存儲鍵
  • CacheBuilder.weakValues():使用弱引用存儲值
  • CacheBuilder.softValues():使用軟引用存儲值

清除什么時候發(fā)生?

也許這個問題有點奇怪缔恳,如果設(shè)置的存活時間為一分鐘宝剖,難道不是一分鐘后這個key就會立即清除掉嗎?我們來分析一下如果要實現(xiàn)這個功能歉甚,那Cache中就必須存在線程來進行周期性地檢查万细、清除等工作,很多cache如redis纸泄、ehcache都是這樣實現(xiàn)的赖钞。
但在GuavaCache中,并不存在任何線程刃滓!它實現(xiàn)機制是在寫操作時順帶做少量的維護工作(如清除)仁烹,偶爾在讀操作時做(如果寫操作實在太少的話),也就是說在使用的是調(diào)用線程咧虎。
這在GuavaCache被稱為“延遲刪除”卓缰,即刪除總是發(fā)生得比較“晚”,這也是GuavaCache不同于其他Cache的地方砰诵!這種實現(xiàn)方式的問題:緩存會可能會存活比較長的時間征唬,一直占用著內(nèi)存。如果使用了復(fù)雜的清除策略如基于容量的清除茁彭,還可能會占用著線程而導(dǎo)致響應(yīng)時間變長总寒。但優(yōu)點也是顯而易見的,沒有啟動線程理肺,不管是實現(xiàn)摄闸,還是使用起來都讓人覺得簡單(輕量)。
如果你還是希望盡可能的降低延遲妹萨,可以創(chuàng)建自己的維護線程年枕,以固定的時間間隔調(diào)用Cache.cleanUp()ScheduledExecutorService可以幫助你很好地實現(xiàn)這樣的定時調(diào)度乎完。不過這種方式依然沒辦法百分百的確定一定是自己的維護線程“命中”了維護的工作熏兄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市树姨,隨后出現(xiàn)的幾起案子摩桶,更是在濱河造成了極大的恐慌,老刑警劉巖帽揪,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硝清,死亡現(xiàn)場離奇詭異,居然都是意外死亡转晰,警方通過查閱死者的電腦和手機芦拿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門砾肺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人防嗡,你說我怎么就攤上這事∠揽玻” “怎么了蚁趁?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長实胸。 經(jīng)常有香客問我他嫡,道長,這世上最難降的妖魔是什么庐完? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任钢属,我火速辦了婚禮,結(jié)果婚禮上门躯,老公的妹妹穿的比我還像新娘淆党。我一直安慰自己,他們只是感情好讶凉,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布染乌。 她就那樣靜靜地躺著,像睡著了一般懂讯。 火紅的嫁衣襯著肌膚如雪荷憋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天褐望,我揣著相機與錄音勒庄,去河邊找鬼。 笑死瘫里,一個胖子當著我的面吹牛实蔽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播减宣,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼盐须,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漆腌?” 一聲冷哼從身側(cè)響起贼邓,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闷尿,沒想到半個月后塑径,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡填具,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年统舀,在試婚紗的時候發(fā)現(xiàn)自己被綠了匆骗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡誉简,死狀恐怖碉就,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闷串,我是刑警寧澤瓮钥,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站烹吵,受9級特大地震影響碉熄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肋拔,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一锈津、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凉蜂,春花似錦琼梆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爆存,卻和暖如春蛉顽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背先较。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工携冤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闲勺。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓曾棕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菜循。 傳聞我的和親對象是個殘疾皇子翘地,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359