作者:Yrion
連結:https://www.cnblogs.com/wyq178/p/9840985.html
前言:緩存在開發中是一個必不可少的優化點,近期在公司的項目重構中,關於緩存優化了很多點,比如在加載一些數據比較多的場景中,會大量使用緩存機制提高接口響應速度,簡介提升用戶體驗。關於緩存,很多人對它都是既愛又恨,愛它的是:它能大幅提升響應效率,恨的是它如果處理不好,沒有用好比如LRU這種策略,沒有及時更新資料庫的數據就會導致數據產生滯後,進而產生用戶的誤讀,或者疑惑。這是很嚴重的一個問題,比如我在公司和某家公司(國內的一線旅遊開發公司)的對接的時候,線上總是出現我們推送接口數據但是網站的數據產生滯後的現象,詢問對方的技術人員,告訴我們是緩存的問題,只要刪除緩存就沒事了,我只能無奈…所以如何處理好緩存,對我們開發人員來說是一個很棘手的問題。不過關於這一切,springboot已經提供給我們很便捷的開發工具!本篇博客就來探索springBoot的緩存註解如何使用!
1.1:搭建springBoot環境
在idea中,搭建一個springboot是很簡單easy的。接下來我簡單說一下步驟:
File->new->projiect->Spring Initializer->next->named->web(選中)->Finish->new Window
1.2:開始緩存
主要是@EnableCaching用於開啟緩存註解的驅動,否則後面使用的緩存都是無效的!
2.1:@CacheConfig
這個註解的的主要作用就是全局配置緩存,比如配置緩存的名字(cacheNames),只需要在類上配置一次,下面的方法就默認以全局配置為主,不需要二次配置,節省了部分代碼。
2.2:@Cacheable
這個註解是最重要的,主要實現的功能再進行一個讀操作的時候。就是先從緩存中查詢,如果查找不到,就會走資料庫的執行方法,這是緩存的註解最重要的一個方法,基本上我們的所有緩存實現都要依賴於它。它具有的屬性為cacheNames:緩存名字,condtion:緩存的條件,unless:不緩存的條件。可以指定SPEL表達式來實現,也可以指定緩存的key,緩存的內部實現一般都是key,value形式,類似於一個Map(實際上cacheable的緩存的底層實現就是concurrenHashMap),指定了key,那麼緩存就會以key作為鍵,以方法的返回結果作為值進行映射。
2.3:@CacheEvict
這個註解主要是配合@Cacheable一起使用的,它的主要作用就是清除緩存,當方法進行一些更新、刪除操作的時候,這個時候就要刪除緩存。如果不刪除緩存,就會出現讀取不到最新緩存的情況,拿到的數據都是過期的。它可以指定緩存的key和conditon,它有一個重要的屬性叫做allEntries默認是false,也可以指定為true,主要作用就是清除所有的緩存,而不以指定的key為主。
2.3:@CachePut
這個註解它總是會把數據緩存,而不會去每次做檢查它是否存在,相比之下它的使用場景就比較少,畢竟我們希望並不是每次都把所有的數據都給查出來,我們還是希望能找到緩存的數據,直接返回,這樣能提升我們的軟體效率。
2.4:@cache
這個註解它是上面的註解的綜合體,包含上面的三個註解(cacheable、cachePut、CacheEvict),可以使用這一個註解來包含上面的所有的註解,看源碼如下
上面的註解總結如下表格:
3.1:建立資料庫
我們來新建一個表,含義為文章,下面的示例將會在這張表中進行操作,所使用的框架為SSM+springboot
3.2:Mapper層
主要就是對Article進行增刪改查的業務操作,映射到具體的xml的sql里,然後用service去調用
3.3:service層
主要需要注意的是我們上述講述的緩存註解都是基於service層(不能放在contoller和dao層),首先我們在類上配置一個CacheConfig,然後配置一個cacheNames,那麼下面的方法都是以這個緩存名字作為默認值,他們的緩存名字都是這個,不必進行額外的配置。當進行select查詢方法的時候,我們配置上@Cacheable,並指定key,這樣除了第一次之外,我們都會把結果緩存起來,以後的結果都會把這個緩存直接返回。而當進行更新數據(刪除或者更新操作)的時候,使用@CacheEvict來清除緩存,防止調用@Cacheabel的時候沒有更新緩存
3.4:controller層
主要是接受客戶端的請求,我們配置了@RestController表示它是一個rest風格的應用程式,在收到add請求會增加一條數據,get請求會查詢一條數據,resh會更新一條數據,rem會刪除一條數據
3.5:測試
這裡使用postman模擬接口請求
3.5.1:首先我們來增加一篇文章:請求add接口:
後台返回表示成功:
我看到後台資料庫已經插入了數據,它的id是11
3.5.2:執行查詢操作
在查詢操作中,getArticle,我使用線程睡眠的方式,模擬了5秒的時間來處理耗時性業務,第一次請求肯定會查詢資料庫,理論上第二次請求,將會走緩存,我們來測試一下:首先執行查詢操作
接口響應成功,再看一下後台列印:表示執行了一次查詢操作,耗時5078秒
好,重點來了,我們再次請求接口看看會返回什麼?理論上,將不會走資料庫執行操作,並且耗時會大大減少:與上面的比對,這次沒有列印執行資料庫查詢操作,證明沒有走資料庫,並且耗時只有5ms,成功了!緩存發揮作用,從5078秒減小到5秒!大大提升了響應速度,哈哈!
3.5.3:更新操作
當我們進行修改操作的時候,我們希望緩存的數據被清空:看接口返回值成功了,再看資料庫
後台控制台列印:
--執行更新操作id:--11
趁熱打鐵,我們再次請求三次查詢接口,看看會返回什麼?每次都會返回這樣的結果,但是我的直觀感受就是第一次最慢,第二次、第三次返回都很快
再看看後台列印了什麼?執行id為11的資料庫查詢操作,這是因為緩存被清空了,所以它又走資料庫了(獲得最新數據),然後後面的查詢都會走緩存!很明顯,實驗成功!
3.5.4:刪除操作
同理,在刪除操作中,執行了一次刪除,那麼緩存也會被清空,查詢的時候會再次走資料庫,這裡就不給具體實驗效果了,如果需要的同學,可以把代碼下載下來,自己測試一下就知道了。
本篇博客介紹了springBoot中緩存的一些使用方法,如何在開發中使用緩存?怎樣合理的使用都是值得我們學習的地方,緩存能大大提升程序的響應速度,提升用戶體驗,不過它適用的場景也是讀多寫少的業務場景,如果數據頻繁修改,緩存將會失去意義,每次還是執行的資料庫操作!如何使用好它,還有更高效的方式,比如使用redis\\memoryCache等專業組件,本篇博客只是探討的spring的註解緩存,相對來說比較簡單。希望起到拋磚引玉的作用,在以後博客中,我將介紹redis如何搭建集群來實現緩存!