本地緩存之神-guava cache

背景

guava cache是google工具包中提供的關(guān)于本地緩存解決方案,提供了基于容量骨杂,時(shí)間和引用的緩存回收方式。
容量:利用LRU算法雄卷,
回收:Java虛擬機(jī)的垃圾回收機(jī)制(堆緩存)搓蚪。

使用場景

愿意花費(fèi)一部分內(nèi)存來提高速度 -- 以空間換時(shí)間
期待有些關(guān)鍵字會(huì)被多次查詢 -- 熱點(diǎn)數(shù)據(jù)
緩存并不需要存儲(chǔ)比RAM中更多的數(shù)據(jù)。Guava caches是一次性運(yùn)行的本地緩存丁鹉,并不會(huì)把數(shù)據(jù)存儲(chǔ)到文件中或者外部服務(wù)器上 -- 不能持久化

功能

創(chuàng)建本地緩存

a.CacheLoader

/**
 * CacheLoader 當(dāng)檢索不存在的時(shí)候妒潭,會(huì)自動(dòng)的加載信息的悴能!
 */
private static LoadingCache<String, String> loadingCache = CacheBuilder
        .newBuilder()
        .maximumSize(2)
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .concurrencyLevel(2)
        .recordStats()
        .build(new CacheLoader<String, String>() {
            @Override
            public String load(String key) throws Exception {
                String value = map.get(key);
                log.info(" load value by key; key:{},value:{}", key, value);
                return value;
            }
        });

public static String getValue(String key) {
    try {
        return loadingCache.get(key);
    } catch (Exception e) {
        log.warn(" get key error ", e);
        return null;
    }
}

b.Callable

private static Cache<String, String> cacheCallable = CacheBuilder
        .newBuilder()
        .maximumSize(2)
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .concurrencyLevel(2)
        .recordStats()
        .build();
/**
 * Callable 如果有緩存則返回;否則運(yùn)算雳灾、緩存漠酿、然后返回
 */
public static String getValue1(String key) {
    try {
         return cacheCallable.get(key, new Callable<String>() {
            @Override
            public String call() throws Exception {
                String value = map.get(key);
                log.info(" load value by key; key:{},value:{}", key, value);
                return value;
            }
        });
    } catch (Exception e) {
        log.warn(" get key error ", e);
        return null;
    }
}

顯示插入-顯示清除

public static void put(String key, String value){
    loadingCache.put(key,value); //手動(dòng)添加值
}

public static void remove(String key){
    loadingCache.invalidate(key); //移除一個(gè)
    loadingCache.invalidateAll(Lists.newArrayList(key)); // 批量移除
    loadingCache.invalidateAll(); // 移除全部-清空
}

移除監(jiān)聽器

a.同步

private static LoadingCache<String, String> loadingCache = CacheBuilder
        .newBuilder()
        .maximumSize(2)
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .concurrencyLevel(2)
        .recordStats()
        .removalListener(new RemovalListener<String, String>() { // sync
            @Override
            public void onRemoval(RemovalNotification<String, String> removal) {
                // TODO remove notification
                log.info("loadingCache is removed. key:{},value:{}",removal.getKey(),removal.getValue());
            }
        })
        .build(new CacheLoader<String, String>() {
            @Override
            public String load(String key) throws Exception {
                String value = map.get(key);
                log.info(" load value by key; key:{},value:{}", key, value);
                return value;
            }
        });

b.異步

// 創(chuàng)建一個(gè)監(jiān)聽器
private static class MyRemovalListener implements RemovalListener<String,String>{
    @Override
    public void onRemoval(RemovalNotification<String, String> removal) {
        // TODO remove notification
        log.info("loadingCache is removed. key:{},value:{}",removal.getKey(),removal.getValue());
    }
}

private static RemovalListener<String, String> async = RemovalListeners.asynchronous(new MyRemovalListener(), Executors.newSingleThreadExecutor());

private static Cache<String, String> cacheCallable = CacheBuilder
        .newBuilder()
        .maximumSize(2)
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .concurrencyLevel(2)
        .recordStats()
        .removalListener(async)
        .build();

為什么使用異步,不需要解釋了吧谎亩!

統(tǒng)計(jì)

//先開啟統(tǒng)計(jì)
private static Cache<String, String> cacheCallable = CacheBuilder
        .newBuilder()
        .maximumSize(2)
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .concurrencyLevel(2)
        .recordStats()
        .removalListener(async)
        .recordStats()//開啟統(tǒng)計(jì)
        .build();
//獲取統(tǒng)計(jì)信息
CacheStats stats = cacheCallable.stats();
>>
public final class CacheStats {
    private final long hitCount;
    private final long missCount;
    private final long loadSuccessCount;
    private final long loadExceptionCount;
    private final long totalLoadTime;
    private final long evictionCount;
...

緩存回收方式

a. 基于容量回收
maximumSize(long):當(dāng)緩存中的元素?cái)?shù)量超過指定值時(shí)炒嘲。
b. 定時(shí)回收
expireAfterAccess(long, TimeUnit):緩存項(xiàng)在給定時(shí)間內(nèi)沒有被讀/寫訪問,則回收团驱。請(qǐng)注意這種緩存的回收順序和基于大小回收一樣摸吠。
expireAfterWrite(long, TimeUnit):緩存項(xiàng)在給定時(shí)間內(nèi)沒有被寫訪問(創(chuàng)建或覆蓋),則回收嚎花。如果認(rèn)為緩存數(shù)據(jù)總是在固定時(shí)候后變得陳舊不可用寸痢,這種回收方式是可取的。
如下文所討論紊选,定時(shí)回收周期性地在寫操作中執(zhí)行啼止,偶爾在讀操作中執(zhí)行。
c. 基于引用回收(Reference-based Eviction)
CacheBuilder.weakKeys():使用弱引用存儲(chǔ)鍵兵罢。當(dāng)鍵沒有其它(強(qiáng)或軟)引用時(shí)献烦,緩存項(xiàng)可以被垃圾回收。
CacheBuilder.weakValues():使用弱引用存儲(chǔ)值卖词。當(dāng)值沒有其它(強(qiáng)或軟)引用時(shí)巩那,緩存項(xiàng)可以被垃圾回收。
CacheBuilder.softValues():使用軟引用存儲(chǔ)值此蜈。軟引用只有在響應(yīng)內(nèi)存需要時(shí)即横,才按照全局最近最少使用的順序回收。

優(yōu)點(diǎn)

線程安全的緩存裆赵,與ConcurrentMap相似东囚,但前者增加了更多的元素失效策略,后者只能顯示的移除元素战授。
提供了三種基本的緩存回收方式:基于容量回收页藻、定時(shí)回收和基于引用回收。定時(shí)回收有兩種:按照寫入時(shí)間植兰,最早寫入的最先回收份帐;按照訪問時(shí)間,最早訪問的最早回收钉跷。
監(jiān)控緩存加載/命中情況弥鹦。
集成了多部操作,調(diào)用get方式,可以在未命中緩存的時(shí)候彬坏,從其他地方獲取數(shù)據(jù)源(DB朦促,redis),并加載到緩存中栓始。

缺點(diǎn)

Guava Cache的超時(shí)機(jī)制不是精確的务冕;
不能持久化本地緩存;
受限于服務(wù)器的內(nèi)存幻赚。

總結(jié)

那話說回來了禀忆,為什么要使用本地緩存呢?比IO更高效落恼,比分布式緩存更穩(wěn)定箩退。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市佳谦,隨后出現(xiàn)的幾起案子戴涝,更是在濱河造成了極大的恐慌,老刑警劉巖钻蔑,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啥刻,死亡現(xiàn)場離奇詭異,居然都是意外死亡咪笑,警方通過查閱死者的電腦和手機(jī)可帽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窗怒,“玉大人映跟,你說我怎么就攤上這事⊙镄椋” “怎么了申窘?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孔轴。 經(jīng)常有香客問我,道長碎捺,這世上最難降的妖魔是什么路鹰? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮收厨,結(jié)果婚禮上晋柱,老公的妹妹穿的比我還像新娘。我一直安慰自己诵叁,他們只是感情好雁竞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般碑诉。 火紅的嫁衣襯著肌膚如雪彪腔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天进栽,我揣著相機(jī)與錄音德挣,去河邊找鬼。 笑死快毛,一個(gè)胖子當(dāng)著我的面吹牛格嗅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播唠帝,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼屯掖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了襟衰?” 一聲冷哼從身側(cè)響起贴铜,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎右蒲,沒想到半個(gè)月后阀湿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瑰妄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年陷嘴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片间坐。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灾挨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出竹宋,到底是詐尸還是另有隱情劳澄,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布蜈七,位于F島的核電站秒拔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏飒硅。R本人自食惡果不足惜砂缩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望三娩。 院中可真熱鬧庵芭,春花似錦、人聲如沸雀监。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至好乐,卻和暖如春匾竿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背曹宴。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工搂橙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笛坦。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓区转,卻偏偏與公主長得像,于是被迫代替她去往敵國和親版扩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子废离,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • Guava Cache以下的特性: automatic loading of entries into the c...
    小鋤禾閱讀 8,616評(píng)論 2 11
  • Google Guava Cache是一種非常優(yōu)秀本地緩存解決方案,提供了基于容量礁芦,時(shí)間和引用的緩存回收方式蜻韭。基于...
    Acamy丶閱讀 25,840評(píng)論 3 34
  • 1柿扣、簡介 線程安全 Guava Cache提供了一種把數(shù)據(jù)(key-value對(duì))緩存到本地(JVM)內(nèi)存中的機(jī)制...
    進(jìn)擊的小鹿閱讀 1,712評(píng)論 0 1
  • guava cache簡介 為什么會(huì)有g(shù)uava cache 實(shí)際開發(fā)中肖方,有時(shí)候會(huì)有一些不常修改,但是經(jīng)常會(huì)被用到...
    黃二的NPE閱讀 848評(píng)論 0 2
  • 項(xiàng)目地址 EZLedView項(xiàng)目地址 效果圖a 原理 廣告牌中經(jīng)常能看到上面這種顯示效果未状,使用LED燈實(shí)現(xiàn)文字甚至...
    大飛機(jī)閱讀 5,107評(píng)論 2 34