版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第SpringBoot使用Caffeine實現(xiàn)緩存的示例代碼目錄為什么要在應(yīng)用程序中添加緩存在SpringBoot應(yīng)用程序中實現(xiàn)緩存SpringBoot提供了什么緩存支持?添加生成依賴項緩存配置緩存方法結(jié)果測試緩存是否正常工作為什么緩存有時會很危險緩存更新/失效緩存復(fù)制嵌入式緩存遠(yuǎn)程緩存服務(wù)器緩存自定義緩存密鑰條件緩存@CachePut緩存失效在本博客中,我們將探討如何使用Spring的緩存框架向任何SpringBoot應(yīng)用程序添加基本緩存支持,如果沒有正確實現(xiàn),還將探討緩存的一些問題。最后但并非最不重要的一點是,我們將看幾個在真實場景中有用的緩存示例。
為什么要在應(yīng)用程序中添加緩存
在深入探討如何向應(yīng)用程序添加緩存之前,首先想到的問題是為什么我們需要在應(yīng)用程序中使用緩存。
假設(shè)有一個包含客戶數(shù)據(jù)的應(yīng)用程序,用戶發(fā)出兩個請求來獲取客戶的數(shù)據(jù)(id=100)。
這就是沒有緩存時的情況。
如您所見,對于每個請求,應(yīng)用程序都會轉(zhuǎn)到數(shù)據(jù)庫獲取數(shù)據(jù)。從數(shù)據(jù)庫獲取數(shù)據(jù)是一項成本高昂的操作,因為它涉及IO。
但是,如果中間有一個緩存存儲,可以在其中臨時存儲短時間的數(shù)據(jù),則可以將這些往返保存到數(shù)據(jù)庫并在IO時間保存。
這就是使用緩存時上述交互的樣子。
在SpringBoot應(yīng)用程序中實現(xiàn)緩存
SpringBoot提供了什么緩存支持?
SpringBoot只提供了一個緩存抽象,您可以使用它將緩存透明、輕松地添加到Spring應(yīng)用程序中。它不提供實際的緩存存儲。但是,它可以與不同類型的緩存提供程序一起工作,如Ehcache、Hazelcast、Redis、Caffee等。SpringBoot的緩存抽象可以添加到方法中(使用注釋)基本上,在執(zhí)行方法之前,Spring框架將檢查方法數(shù)據(jù)是否已經(jīng)緩存如果是,則它將從緩存中獲取數(shù)據(jù)。否則它將執(zhí)行該方法并緩存數(shù)據(jù)它還提供了從緩存中更新或刪除數(shù)據(jù)的抽象。在我們當(dāng)前的博客中,我們將了解如何使用Caffeine添加緩存,Caffeine是一種基于Java8的高性能、接近最優(yōu)的緩存庫。
您可以在application.yaml文件中指定使用哪個緩存提供程序來設(shè)置spring.cache.type屬性。
但是,如果沒有提供屬性,Spring將根據(jù)添加的庫自動檢測緩存提供程序。
添加生成依賴項
現(xiàn)在假設(shè)您已經(jīng)啟動并運行了基本的Springboot應(yīng)用程序,讓我們添加緩存依賴項。
打開build.gradle文件,并添加以下依賴項以啟用SpringBoot的緩存
compile('org.springframework.boot:spring-boot-starter-cache')
接下來我們將添加對Caffeine的依賴
compilegroup:'com.github.ben-manes.caffeine',name:'caffeine',version:'2.8.5'
緩存配置
現(xiàn)在我們需要在SpringBoot應(yīng)用程序中啟用緩存。
為此,我們需要創(chuàng)建一個配置類并提供注釋@EnableCaching。
@Configuration
@EnableCaching
publicclassCacheConfig{
}
現(xiàn)在這個類是一個空類,但是我們可以向它添加更多配置(如果需要)。
現(xiàn)在我們已經(jīng)啟用了緩存,讓我們提供緩存名稱和緩存屬性的配置,如緩存大小、緩存過期時間等
最簡單的方法是在application.yaml中添加配置
spring:
cache:
cache-names:customers,users,roles
caffeine:
spec:maximumSize=500,expireAfterAccess=60s
上述配置執(zhí)行以下操作
將可用緩存名稱限制為客戶、用戶和角色。將最大緩存大小設(shè)置為500。當(dāng)緩存中的對象數(shù)達(dá)到此限制時,將根據(jù)緩存逐出策略從緩存中刪除對象。將緩存過期時間設(shè)置為1分鐘。這意味著項目將在添加到緩存1分鐘后從緩存中刪除。
還有另一種配置緩存的方法,而不是在application.yaml文件中配置緩存。
您可以在緩存配置類中添加并提供一個CacheManagerBean,該Bean可以完成與上面在application.yaml中的配置完全相同的工作
@Bean
publicCacheManagercacheManager(){
CaffeineObject,ObjectcaffeineCacheBuilder=
Caffeine.newBuilder()
.maximumSize(500)
.expireAfterAccess(
1,TimeUnit.MINUTES);
CaffeineCacheManagercacheManager=
newCaffeineCacheManager(
"customers","roles","users");
cacheManager.setCaffeine(caffeineCacheBuilder);
returncacheManager;
}
在我們的代碼示例中,我們將使用Java配置。
我們可以在Java中做更多的事情,比如配置RemovalListener,當(dāng)一個項從緩存中刪除時執(zhí)行RemovalListener,或者啟用緩存統(tǒng)計記錄,等等。
緩存方法結(jié)果
在我們使用的示例Springboot應(yīng)用程序中,我們已經(jīng)有了以下APIGET/API/v1/customer/{id}來檢索客戶記錄。
我們將向CustomerService類的getCustomerByd(longCustomerId)方法添加緩存。
要做到這一點,我們只需要做兩件事
1.將注釋@CacheConfig(cacheNames=customers)添加到CustomerService類
提供此選項將確保CustomerService的所有可緩存方法都將使用緩存名稱customers
2.向方法OptionalgetCustomerById(LongcustomerId)添加注釋@Cacheable
@Service
@Log4j2
@CacheConfig(cacheNames="customers")
publicclassCustomerService{
@Autowired
privateCustomerRepositorycustomerRepository;
@Cacheable
publicOptionalCustomergetCustomerById(LongcustomerId){
("Fetchingcustomerbyid:{}",customerId);
returncustomerRepository.findById(customerId);
}
另外,在方法getCustomerById()中添加一個LOGGER語句,以便我們知道服務(wù)方法是否得到執(zhí)行,或者值是否從緩存返回。
復(fù)制代碼代碼如下:("Fetchingcustomerbyid:{}",customerId);
測試緩存是否正常工作
這就是緩存工作所需的全部內(nèi)容?,F(xiàn)在是測試緩存的時候了。
啟動您的應(yīng)用程序,并點擊客戶獲取url
http://localhost:8080/api/v1/customer/
在第一次API調(diào)用之后,您將在日志中看到以下行Fetchingcustomerbyid。
但是,如果再次點擊API,您將不會在日志中看到任何內(nèi)容。這意味著該方法沒有得到執(zhí)行,并且從緩存返回客戶記錄。
現(xiàn)在等待一分鐘(因為緩存過期時間設(shè)置為1分鐘)。
一分鐘后再次點擊GETAPI,您將看到下面的語句再次被記錄通過id獲取客戶。
這意味著客戶記錄在1分鐘后從緩存中刪除,必須再次從數(shù)據(jù)庫中獲取。
為什么緩存有時會很危險
緩存更新/失效
通常我們緩存GET調(diào)用,以提高性能。
但我們需要非常小心的是緩存對象的更新/刪除。
@CachePut
@cacheexecute
如果未將@CachePut/@cacheexecute放入更新/刪除方法中,GET調(diào)用中緩存返回的對象將與數(shù)據(jù)庫中存儲的對象不同??紤]下面的示例場景。
如您所見,第二個請求已將人名更新為JohnSmith。但由于它沒有更新緩存,因此從此處開始的所有請求都將從緩存中獲取過時的個人記錄(JohnDoe),直到該項在緩存中被刪除/更新。
緩存復(fù)制
大多數(shù)現(xiàn)代web應(yīng)用程序通常有多個應(yīng)用程序節(jié)點,并且在大多數(shù)情況下都有一個負(fù)載平衡器,可以將用戶請求重定向到一個可用的應(yīng)用程序節(jié)點。
這種類型的部署為應(yīng)用程序提供了可伸縮性,任何用戶請求都可以由任何一個可用的應(yīng)用程序節(jié)點提供服務(wù)。
在這些分布式環(huán)境(具有多個應(yīng)用服務(wù)器節(jié)點)中,緩存可以通過兩種方式實現(xiàn)
應(yīng)用服務(wù)器中的嵌入式緩存(正如我們現(xiàn)在看到的)遠(yuǎn)程緩存服務(wù)器
嵌入式緩存
嵌入式緩存駐留在應(yīng)用程序服務(wù)器中,它隨應(yīng)用程序服務(wù)器啟動/停止。由于每臺服務(wù)器都有自己的緩存副本,因此對其緩存的任何更改/更新都不會自動反映在其他應(yīng)用程序服務(wù)器的緩存中。
考慮具有嵌入式緩存的多節(jié)點應(yīng)用服務(wù)器的下面場景,其中用戶可以根據(jù)應(yīng)用服務(wù)器為其請求服務(wù)而得到不同的結(jié)果。
正如您在上面的示例中所看到的,更新請求更新了ApplicationNode2的數(shù)據(jù)庫和嵌入式緩存。
但是,ApplicationNode1的嵌入式緩存未更新,并且包含過時數(shù)據(jù)。因此,ApplicationNode1的任何請求都將繼續(xù)服務(wù)于舊數(shù)據(jù)。
要解決這個問題,您需要實現(xiàn)CACHEREPLICATION其中任何一個緩存中的任何更新都會自動復(fù)制到其他緩存(下圖中顯示為藍(lán)色虛線)
遠(yuǎn)程緩存服務(wù)器
解決上述問題的另一種方法是使用遠(yuǎn)程緩存服務(wù)器(如下所示)。
然而,這種方法的最大缺點是增加了響應(yīng)時間這是由于從遠(yuǎn)程緩存服務(wù)器獲取數(shù)據(jù)時的網(wǎng)絡(luò)延遲(與內(nèi)存緩存相比)
緩存自定義
到目前為止,我們看到的緩存示例是向應(yīng)用程序添加基本緩存所需的唯一代碼。
然而,現(xiàn)實世界的場景可能不是那么簡單,可能需要進(jìn)行一些定制。在本節(jié)中,我們將看到幾個這樣的例子
緩存密鑰
我們知道緩存是密鑰、值對的存儲。
示例1:默認(rèn)緩存鍵具有單參數(shù)的方法
最簡單的緩存鍵是當(dāng)方法只有一個參數(shù),并且該參數(shù)成為緩存鍵時。在下面的示例中,LongcustomerId是緩存鍵
示例2:默認(rèn)緩存鍵具有多個參數(shù)的方法
在下面的示例中,緩存鍵是所有三個參數(shù)的SimpleKeycountryId、regionId、personId。
示例3:自定義緩存密鑰
在下面的示例中,我們將此人的emailAddress指定為緩存的密鑰
示例4:使用KeyGenerator的自定義緩存密鑰
讓我們看看下面的示例如果要緩存當(dāng)前登錄用戶的所有角色,該怎么辦。
該方法中沒有提供任何參數(shù),該方法在內(nèi)部獲取當(dāng)前登錄用戶并返回其角色。
為了實現(xiàn)這個需求,我們需要創(chuàng)建一個如下所示的自定義密鑰生成器
然后我們可以在我們的方法中使用這個鍵生成器,如下所示。
條件緩存
在某些用例中,我們只希望在滿足某些條件的情況下緩存結(jié)果
示例1(支持java.util.Optional僅當(dāng)存在時才緩存)
僅當(dāng)結(jié)果中存在person對象時,才緩存person對象。
@Cacheable(value="persons",unless="#result.id")
publicOptionalPersongetPerson(LongpersonId)
示例2(如果需要,by-pass緩存)
@Cacheable(value="persons",condition="#fetchFromCache")
publicOptionalPersongetPerson(longpersonId,booleanfetchFromCache)
僅當(dāng)方法參數(shù)fetchFromCache為true時,才從緩存中獲取人員。通過這種方式,方法的調(diào)用方有時可以決定繞過緩存并直接從數(shù)據(jù)庫獲取值。
示例3(基于對象屬性的條件計算)
僅當(dāng)價格低于500且產(chǎn)品有庫存時,才緩存產(chǎn)品。
@Cacheable(
value="products",
condition="#product.price500",
unless="#result.outOfStock")
publicProductfindProduct(Productproduct)
@CachePut
我們已經(jīng)看到@Cacheable用于將項目放入緩存。
但是,如果該對象被更新,并且我們想要更新緩存,該怎么辦?
我們已經(jīng)在前面的一節(jié)中看到,不更新緩存post任何更新操作都可能導(dǎo)致從緩存返回錯誤的結(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026浙江開化農(nóng)村商業(yè)銀行寒假實習(xí)生社會實踐活動招募備考考試試題附答案解析
- 2025廣東佛山市順德區(qū)沙滘初級中學(xué)第二學(xué)期臨聘教師招聘備考考試試題附答案解析
- 2026福建南平市建陽區(qū)文化體育和旅游局招聘1人備考考試題庫附答案解析
- 物業(yè)公司生產(chǎn)責(zé)任制度
- 原材料生產(chǎn)過程管理制度
- 2026重慶市萬州區(qū)燕山鄉(xiāng)人民政府招聘全日制公益性崗位1人備考考試試題附答案解析
- 倉鼠生產(chǎn)管理員工制度
- 生產(chǎn)企業(yè)黑名單制度
- 2026年河北承德市教育局公開選聘急需緊缺學(xué)科教師39名參考考試題庫附答案解析
- 戒毒所生產(chǎn)車間制度
- 中國醫(yī)護服裝行業(yè)未來發(fā)展趨勢分析及投資規(guī)劃建議研究報告
- 《廣州天河商圈》課件
- H31341 V2.5 HCIP-TranSmission 傳輸網(wǎng)練習(xí)試題及答案
- 下肢靜脈曲張課件
- (高清版)DZT 0428-2023 固體礦產(chǎn)勘查設(shè)計規(guī)范
- XXX縣村鎮(zhèn)空氣源熱泵區(qū)域集中供熱項目可行性研究報告
- 湖州昆侖億恩科電池材料有限公司年產(chǎn)40000噸鋰離子電池電解液項目環(huán)境影響報告
- 幼兒園班級體弱兒管理總結(jié)
- 肥胖患者圍術(shù)期麻醉管理
- 核酸印跡與分子雜交
- 金屬罐三片罐結(jié)構(gòu)分析
評論
0/150
提交評論