最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java開發(fā)利器之Guava?Cache的使用教程

 更新時(shí)間:2022年09月21日 09:21:51   作者:指北君  
緩存技術(shù)被認(rèn)為是減輕服務(wù)器負(fù)載、降低網(wǎng)絡(luò)擁塞、增強(qiáng)Web可擴(kuò)展性的有效途徑之一。今天咱們就來聊聊Guava?Cache本地緩存,感興趣的可以了解一下

前言

緩存技術(shù)被認(rèn)為是減輕服務(wù)器負(fù)載、降低網(wǎng)絡(luò)擁塞、增強(qiáng)Web可擴(kuò)展性的有效途徑之一,其基本思想是利用客戶訪問的時(shí)間局部性(Temproral Locality)原理, 將客戶訪問過的內(nèi)容在Cache中存放一個(gè)副本,當(dāng)該內(nèi)容下次被訪問時(shí),不必連接到駐留網(wǎng)站,而是由Cache中保留的副本提供。

在企業(yè)Web應(yīng)用中,通過緩存技術(shù)能夠提高請求的響應(yīng)速度;減少系統(tǒng)IO開銷;降低系統(tǒng)數(shù)據(jù)讀寫壓力...

緩存的意義

首先我們要知道,在我們開發(fā)過程中,為什么要使用緩存,緩存能夠?yàn)槲覀儙砟男┖锰帲?/p>

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

  • 通過緩存承載系統(tǒng)壓力,減少對系統(tǒng)或網(wǎng)絡(luò)資源訪問而引起的性能消耗,在流量較大時(shí)能夠很好地減少系統(tǒng)擁塞
  • 緩存一般都是使用存取非??斓慕M件實(shí)現(xiàn),通過緩存能夠快速響應(yīng)客戶端請求,從而降低客戶訪問延遲,提審系統(tǒng)響應(yīng)速度
  • 在配備負(fù)載均衡的應(yīng)用架構(gòu)中,通過緩存靜態(tài)資源能夠有效減少服務(wù)器負(fù)載壓力
  • 當(dāng)下游應(yīng)用故障時(shí),通過返回緩存數(shù)據(jù)能夠在一定程度上增強(qiáng)應(yīng)用容錯(cuò)性

缺點(diǎn)

  • 緩存數(shù)據(jù)與實(shí)際數(shù)據(jù)不一致問題問題
  • 高并發(fā)場景時(shí)存在緩存擊穿、緩存穿透、緩存雪崩等問題

總的來說,緩存主要是針對高頻訪問但低頻更新的數(shù)據(jù),從而加快服務(wù)器響應(yīng)與原資源訪問壓力

Guava Cache是一個(gè)相對比較簡單并且容易理解的本地緩存框架,今天主要以此為開端來認(rèn)識(shí)并學(xué)習(xí)如何使用緩存

Guava Cache特色

本地緩存我們可以簡單的理解為Map,將數(shù)據(jù)保存到Map(內(nèi)存)中,下次使用該數(shù)據(jù)時(shí),通過key直接從Map中取即可。但是使用Map會(huì)有一些幾個(gè)問題需要考慮:

  • 緩存的容量。不可能無限制的對數(shù)據(jù)進(jìn)行緩存,當(dāng)數(shù)據(jù)較大時(shí)占用系統(tǒng)資源會(huì)導(dǎo)致主業(yè)務(wù)受影響
  • 緩存的清理。有些緩存使用頻率很低,如果一直占用資源也是一種浪費(fèi)
  • 并發(fā)訪問時(shí)的效率問題。緩存更新時(shí)瞬時(shí)對系統(tǒng)、網(wǎng)絡(luò)資源的訪問導(dǎo)致故障
  • 緩存使用情況評估

當(dāng)然以上問題我們通過我們對Map包裝下即可實(shí)現(xiàn),當(dāng)然Guava Cache也就是基于這種思想,底層原理則是基于Map實(shí)現(xiàn),我們看下其有哪些特色:

緩存過期和淘汰機(jī)制

通過設(shè)置Key的過期時(shí)間,包括訪問過期和創(chuàng)建過期;設(shè)置緩存容量大小,采用LRU的方式,選擇最近最久的緩存進(jìn)行刪除。

并發(fā)處理能力

Cache主要基于CurrentHashMap實(shí)現(xiàn)線程安全;通過對key的計(jì)算,基于分段鎖,提高緩存讀寫效率,降低鎖的粒度,提升并發(fā)能力

更新鎖定

在緩存中查詢某個(gè)key,如果不存在,則查源數(shù)據(jù),并回填緩存。在高并發(fā)下會(huì)出現(xiàn),多次查詢元數(shù)據(jù)并重復(fù)回填緩存,可能會(huì)造成系統(tǒng)故障,最明顯的DB服務(wù)器宕機(jī),性能下降等。GuavaCache通過在CacheLoader調(diào)用load方法時(shí),對同一個(gè)key同一時(shí)刻只會(huì)有一個(gè)請求去讀源數(shù)據(jù)并回填緩存,后面的請求則直接繼續(xù)從緩存讀取,有效阻斷并發(fā)請求對資源服務(wù)的影響。

集成數(shù)據(jù)源

一般我們在業(yè)務(wù)中操作緩存,都會(huì)操作緩存和數(shù)據(jù)源兩部分GuavaCache的get可以集成數(shù)據(jù)源,在從緩存中讀取不到時(shí)可以從數(shù)據(jù)源中讀取數(shù)據(jù)并回填緩存

監(jiān)控統(tǒng)計(jì)

監(jiān)控緩存加載次數(shù)、命中率、失誤率以及數(shù)據(jù)加載時(shí)長等

API介紹

1.緩存構(gòu)建

ManualCache 此時(shí)Cache相當(dāng)于一個(gè)Map,對數(shù)據(jù)進(jìn)行CRUD操作時(shí),需要同步操作緩存Map; 高并發(fā)情況時(shí),可以使用get(k,loader)讀緩存,通過Cache鎖機(jī)制,防止對系統(tǒng)資源(DB)的并發(fā)訪問 通過put方法實(shí)現(xiàn)緩存的存入與更新;

LoadingCache 此時(shí)構(gòu)建的是一個(gè)實(shí)現(xiàn)了Cache接口的LoadingCache,相比ManualCache,提供了緩存回填機(jī)制,即當(dāng)緩存不存在時(shí),會(huì)基于CacheLoader查詢數(shù)據(jù)并將結(jié)果回填到緩存, 在高并發(fā)時(shí),可以有效地基于緩存鎖減少對系統(tǒng)資源的調(diào)用。此時(shí)僅需要關(guān)注緩存的使用,緩存的更新與存入都是基于CacheLoader實(shí)現(xiàn);

2.緩存獲取

get(k) 根據(jù)key查詢,沒有則觸發(fā)load;如果load為空則拋出異常

getUnchecked(k) 緩存不存在或返回為null會(huì)拋出檢查異常

get(k,loader) 根據(jù)key查詢,沒有則調(diào)用loader方法,且對結(jié)果緩存;如果loader返回null則拋出異常,此時(shí)不會(huì)調(diào)用默認(rèn)的load方法

getIfPresent(k) 有緩存則返回,否則返回null,不會(huì)觸發(fā)load

3.緩存更新

put(k,v) 如果緩存已經(jīng)存在,則會(huì)先進(jìn)行一次刪除

4.緩存刪除

invalidate(k) 根據(jù)key使緩存失效

過期  通過配置的過期參數(shù),比如expireAfterAccess、expireAfterWrite、refreshAfterWrite

過載  當(dāng)緩存數(shù)據(jù)量超過設(shè)置的最大值時(shí),根據(jù)LRU算法進(jìn)行刪除

引用  構(gòu)建緩存時(shí)將鍵值設(shè)置為弱引用、軟引用,基于GC機(jī)制來清理緩存

5.統(tǒng)計(jì)

hitRate() 緩存命中率;

hitMiss() 緩存失誤率;

loadCount() 加載次數(shù);

averageLoadPenalty() 加載新值的平均時(shí)間,單位為納秒;

evictionCount() 緩存項(xiàng)被回收的總數(shù),不包括顯式清除。

Builder配置

配置描述
expireAfterAccess多久沒有讀寫則過期
expireAfterWrite寫入后多久沒更新自動(dòng)過期,先刪除,后load
refreshAfterWrite上一次更新后多久自動(dòng)刷新,先reload后刪除,并發(fā)時(shí)會(huì)取到老的數(shù)據(jù)
removalListener設(shè)置緩存刪除監(jiān)聽
initialCapacity緩存初始化大小
concurrencyLevel最大的并發(fā)數(shù),可以理解為并發(fā)線程數(shù)量
maximumSize最大緩存數(shù)量,超過時(shí)會(huì)根據(jù)策略清除
maximumWeight最大權(quán)重容量數(shù),僅用于確定緩存是否超過容量
recordStats緩存命中統(tǒng)計(jì)

簡單示例

ManualCache模式

下面以用戶服務(wù)為例,我們看下如何在增刪改查方法中使用緩存:

private?Cache<String,?User>?cache?=?CacheBuilder.newBuilder()
????????????.expireAfterWrite(3,?TimeUnit.SECONDS)//寫入多久沒更新自動(dòng)過期,先刪除,后load
????????????.removalListener(new?RemovalListener<Object,?Object>()?{
????????????????@Override
????????????????public?void?onRemoval(RemovalNotification<Object,?Object>?notification)?{
????????????????????LOGGER.info("{}?remove?{}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd?HH:mm:ss")),notification.getKey());
????????????????}
????????????})
????????????.initialCapacity(20)?//初始化容量
????????????.concurrencyLevel(10)?//?并發(fā)
????????????.maximumSize(100)?//最多緩存數(shù)量
????????????.recordStats()?//?開啟統(tǒng)計(jì)
????????????.build();

@Override
????public?User?getUser(String?id){
//????????緩存不存在時(shí),通過LocalCache鎖機(jī)制,防止對數(shù)據(jù)庫的高頻訪問
???????User?user;
???????try?{
???????????user?=?cache.get(id,()->?{
???????????????LOGGER.info("緩存不存在,從loader加載數(shù)據(jù)");
???????????????return?userDao.get(id);
???????????});
???????}?catch?(ExecutionException?e)?{
???????????throw?new?RuntimeException(e);
???????}
????????return?user;
????}

????@Override
????public?User?saveOrUpdateUser(User?user){
????????userDao.saveOrUpdate(user);
????????cache.put(user.getId(),user);
????????return?user;
????}

????@Override
????public?void?removeUser(String?id){
????????userDao.remove(id);
????????cache.invalidate(id);
????}

LoadingCache模式

private?LoadingCache<String,?User>?cache?=?CacheBuilder.newBuilder()
????????????//?省略
????????????.build(new?CacheLoader<String,?User>()?{
????????????????@Override
????????????????public?User?load(String?key)?throws?Exception?{
????????????????????LOGGER.info("{}?load?{}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd?HH:mm:ss")),key);
????????????????????return?userDao.get(key);
????????????????}

????????????????@Override
????????????????public?ListenableFuture<User>?reload(String?key,?User?oldUser)?throws?Exception?{
????????????????????LOGGER.info("{}?reload?{}",?LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd?HH:mm:ss")),key);
????????????????????ListenableFutureTask<User>?listenableFutureTask?=?ListenableFutureTask.create(()?->?userDao.get(key));
????????????????????CompletableFuture.runAsync(listenableFutureTask);
????????????????????return?listenableFutureTask;
????????????????}
????????????});

????@SneakyThrows
????@Override
????public?User?getUser(String?id){
????????//?緩存不存在或返回為null會(huì)拋出異常
????????try?{
????????????return?cache.getUnchecked(id);
????????}?catch?(Exception?e)?{
????????????return?null;
????????}
????}

????@Override
????public?User?saveOrUpdateUser(User?user){
????????cache.invalidate(user.getId());
????????return?userDao.saveOrUpdate(user);
????}

????@Override
????public?void?removeUser(String?id){
????????cache.invalidate(id);
????????userDao.remove(id);
????}

總結(jié):第一種寫法更像是前面說到的Map,在對數(shù)據(jù)進(jìn)行CRUD操作時(shí),需要用戶手動(dòng)對緩存進(jìn)行同步的更新或刪除操作,所以叫ManualCache(手動(dòng)),當(dāng)然Guava Cache對Map的加強(qiáng)依然有效,比如過期清除,緩存容量限制。第二種方式寫法差不多,主要是引入了CacheLoader接口,在讀數(shù)據(jù)時(shí)緩存數(shù)據(jù)不存在時(shí),通過CacheLoader的load方法先寫緩存后返回?cái)?shù)據(jù)

注意

1.expireAfterWrite、refreshAfterWrite的區(qū)別

在refreshAfterWrite導(dǎo)致緩存失效時(shí),并不會(huì)因?yàn)楦戮彺娑枞彺鏀?shù)據(jù)的返回,只不過是返回老的數(shù)據(jù)

2.不能緩存null

有時(shí)候?yàn)榱藢⒅禐閚ull的數(shù)據(jù)統(tǒng)一緩存,這樣就不會(huì)因?yàn)闆]有緩存數(shù)據(jù)而訪問數(shù)據(jù)庫造成壓力

3.讀寫時(shí)才進(jìn)行刪除

Guava Cache的緩存數(shù)據(jù)刪除是在更新或?qū)懭霑r(shí)才會(huì)觸發(fā),沒有單獨(dú)的調(diào)度服務(wù)完成這一工作

本地緩存

類似的本地緩存還有,有興趣的可以自己嘗試,其實(shí)實(shí)現(xiàn)思想應(yīng)該也差不多

到此這篇關(guān)于Java開發(fā)利器之Guava Cache的使用教程的文章就介紹到這了,更多相關(guān)Java Guava Cache內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring?jpa?審計(jì)功能自定義填充字段方式

    spring?jpa?審計(jì)功能自定義填充字段方式

    這篇文章主要介紹了spring?jpa審計(jì)功能自定義填充字段方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java報(bào)錯(cuò)狀態(tài)碼問題

    java報(bào)錯(cuò)狀態(tài)碼問題

    這篇文章主要介紹了java報(bào)錯(cuò)狀態(tài)碼問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息的示例

    SpringBoot集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息的示例

    這篇文章主要介紹了SpringBoot集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java內(nèi)部類詳解

    Java內(nèi)部類詳解

    內(nèi)部類在 Java 里面算是非常常見的一個(gè)功能了,在日常開發(fā)中我們肯定多多少少都用過,這里總結(jié)一下關(guān)于 Java 中內(nèi)部類的相關(guān)知識(shí)點(diǎn)和一些使用內(nèi)部類時(shí)需要注意的點(diǎn)。
    2020-02-02
  • Spring根據(jù)XML配置文件注入屬性的方法

    Spring根據(jù)XML配置文件注入屬性的方法

    下面小編就為大家?guī)硪黄猄pring根據(jù)XML配置文件注入屬性的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • Java報(bào)錯(cuò)Java.text.ParseException的解決方法匯總

    Java報(bào)錯(cuò)Java.text.ParseException的解決方法匯總

    在Java開發(fā)的復(fù)雜世界中,錯(cuò)誤處理是開發(fā)者必須面對的關(guān)鍵挑戰(zhàn)之一,其中,Java.text.ParseException就像一個(gè)隱藏在代碼叢林中的陷阱,常常讓開發(fā)者們陷入困惑,本文給大家介紹了Java報(bào)錯(cuò)Java.text.ParseException的解決方法,需要的朋友可以參考下
    2024-10-10
  • Java中輸入與輸出的方法總結(jié)

    Java中輸入與輸出的方法總結(jié)

    這篇文章主要為大家總結(jié)了一下Java中輸入與輸出的三種方法,文中通過示例詳細(xì)的講解了一下這些方法的使用,需要的小伙伴可以參考一下
    2022-04-04
  • Springboot自帶定時(shí)任務(wù)實(shí)現(xiàn)動(dòng)態(tài)配置Cron參數(shù)方式

    Springboot自帶定時(shí)任務(wù)實(shí)現(xiàn)動(dòng)態(tài)配置Cron參數(shù)方式

    這篇文章主要介紹了Springboot自帶定時(shí)任務(wù)實(shí)現(xiàn)動(dòng)態(tài)配置Cron參數(shù)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 23種設(shè)計(jì)模式(6)java裝飾者模式

    23種設(shè)計(jì)模式(6)java裝飾者模式

    這篇文章主要為大家詳細(xì)介紹了23種設(shè)計(jì)模式之java裝飾者模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • java Thumbnails 圖片處理的使用

    java Thumbnails 圖片處理的使用

    這篇文章主要介紹了java Thumbnails 圖片處理的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論

周口市| 格尔木市| 陆良县| 大余县| 临泽县| 蓝山县| 贵阳市| 永登县| 伊宁市| 金堂县| 佳木斯市| 黑山县| 明水县| 沿河| 黑山县| 无棣县| 图们市| 竹山县| 武功县| 桦南县| 东明县| 定远县| 河池市| 团风县| 大悟县| 嘉黎县| 清苑县| 荣成市| 治多县| 泰宁县| 项城市| 金华市| 望都县| 汝南县| 清水县| 武冈市| 来宾市| 策勒县| 临潭县| 鄢陵县| 清河县|