Spring中的@Cacheable緩存注解詳解
1 什么是緩存
第一個(gè)問題,首先要搞明白什么是緩存,緩存的意義是什么。
對(duì)于普通業(yè)務(wù),如果要查詢一個(gè)數(shù)據(jù),一般直接select數(shù)據(jù)庫進(jìn)行查找。但是在高流量的情況下,直接查找數(shù)據(jù)庫就會(huì)成為性能的瓶頸。因?yàn)閿?shù)據(jù)庫查找的流程是先要從磁盤拿到數(shù)據(jù),再刷新到內(nèi)存,再返回?cái)?shù)據(jù)。磁盤相比于內(nèi)存來說,速度是很慢的,為了提升性能,就出現(xiàn)了基于內(nèi)存的緩存。
這種基于內(nèi)存的緩存,由于無法跟磁盤頻繁進(jìn)行存儲(chǔ),所以無法保證數(shù)據(jù)的完整性,隨時(shí)有可能丟失,所以架構(gòu)一般使用數(shù)據(jù)庫加緩存的方式,數(shù)據(jù)庫用來持久化數(shù)據(jù),緩存用來處理大流量。
2 本地緩存和集中式緩存
緩存按照存儲(chǔ)方式可以分為這本地緩存和集中式緩存。
本地緩存顧名思義就是存儲(chǔ)在本地上,例如靜態(tài)變量就可以說是一種本地緩存,存儲(chǔ)在了JVM中,或者說自己本地搭建的項(xiàng)目用的redis也算是本地緩存,因?yàn)榫彺婧蛻?yīng)用都在一臺(tái)機(jī)器上。
本地緩存效率很高,直接讀取內(nèi)存,沒有網(wǎng)絡(luò)延遲,但是可用性很低,因?yàn)槌霈F(xiàn)單點(diǎn)故障的話,數(shù)據(jù)庫和系統(tǒng)都會(huì)宕機(jī)。
對(duì)于大型項(xiàng)目來說,都會(huì)有集中式緩存,例如redis集群。緩存和應(yīng)用服務(wù)器是分離的,服務(wù)器需要通過網(wǎng)絡(luò)請(qǐng)求從緩存獲取數(shù)據(jù),一般應(yīng)用服務(wù)器也會(huì)采取集群的方式,這樣可以保證高可用,數(shù)據(jù)不易丟失,而且也能保證各個(gè)服務(wù)器的緩存數(shù)據(jù)一致。
對(duì)于分布式應(yīng)用來說,本地緩存還會(huì)出現(xiàn)緩存不一致的問題,因?yàn)槊總€(gè)服務(wù)器的本地緩存都是獨(dú)立的。
3 本地緩存的優(yōu)點(diǎn)
剛才說了這么多本地緩存的缺點(diǎn),那為什么還要用呢?
因?yàn)槿绻挤旁诩惺骄彺嬷?,網(wǎng)絡(luò)延遲會(huì)成為性能的瓶頸。因?yàn)椴辉诒镜貎?nèi)存,讀取的時(shí)間需要加上網(wǎng)絡(luò)通信的時(shí)間。所以在對(duì)性能要求更大或者緩存內(nèi)容不需要持久化、不需要一致性的情況下,本地緩存更適合。
所以一般的大型項(xiàng)目都采用本地緩存和集中式緩存混合使用的方式。
4 Spring對(duì)于緩存的支持
終于說到正題,本地緩存可以通過spring更簡(jiǎn)單的管理和使用。
springboot和springmvc都支持緩存,其中CacheManager是Spring提供的緩存接口。
4.1 spring支持的CacheManager
看著非常多,實(shí)際上正常用的只有ConcurrentMapCacheManager
,EhCacheCacheManager
,GuavaCacheManager
(一般使用redis,我們需要更靈活的對(duì)redis鍵值進(jìn)行操作,所以不用RedisCacheManager
),我們重點(diǎn)去講一下這個(gè)GuavaCacheManager
。
4.2 GuavaCache
Guava是谷歌開源的Java庫,其中的代表就有這個(gè)緩存。
GuavaCache的原理大概是LRU+ConcurrentHashMap
,加載在JVM的本地緩存
4.3 引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> //有可能需要這個(gè) <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.5.RELEASE</version> </dependency>
4.4 創(chuàng)建配置類
@EnableCaching @Configuration public class GuavaCacheConfig { @Bean public CacheManager cacheManager() { GuavaCacheManager cacheManager = new GuavaCacheManager(); cacheManager.setCacheBuilder( CacheBuilder.newBuilder(). expireAfterWrite(3, TimeUnit.MINUTES)); return cacheManager; } }
@EnableCaching用來開啟注解功能,這里設(shè)置的失效時(shí)間是3分鐘。
Guava Cache 除了代碼中提到的設(shè)置緩存過期時(shí)間的策略外,還有其他的策略。下面是 Guava Cache 設(shè)置緩存過期時(shí)間的策略:
- expireAfterAccess: 當(dāng)緩存項(xiàng)在指定的時(shí)間段內(nèi)沒有被讀或?qū)懢蜁?huì)被回收。
- expireAfterWrite:當(dāng)緩存項(xiàng)在指定的時(shí)間段內(nèi)沒有更新就會(huì)被回收,如果我們認(rèn)為緩存數(shù)據(jù)在一段時(shí)間后數(shù)據(jù)不再可用,那么可以使用該種策略。
- refreshAfterWrite:當(dāng)緩存項(xiàng)上一次更新操作之后的多久會(huì)被刷新。
4.5 緩存注解
標(biāo)題終于出現(xiàn)了
我這里就主要解釋下@Cacheable的用法,因?yàn)檫@個(gè)比較常見(其他的我也沒用過)
4.6 @Cacheable的用法
常用參數(shù)有
#
代表的是EL表達(dá)式
這里的key和value和我們以為的緩存鍵值對(duì)是不一樣的
value+key 只是我們緩存鍵的名字,真正的值是方法的返回值。
舉一個(gè)例子
@Cacheable(value = "olympic_match_new_action",key = "'get_relate_news_'+#rsc") public List<MatchNewsVO> getRelateNews(String rsc){ .... }
一般value取service名,key取方法名,取名按照數(shù)據(jù)庫的下劃線方式。后面那個(gè)#rsc指的是傳進(jìn)來的參數(shù),這些都是鍵。返回的List就是緩存的值。
5 @Cacheable失效的原因
在配置正常的情況下,本人親歷的失效原因就是一個(gè)類的方法調(diào)用了帶有緩存的方法,結(jié)果緩存失效。
我使用service的A方法,想調(diào)用這個(gè)service的緩存B方法,這樣是不行的。
原因是@Cacheable是由AOP代理實(shí)現(xiàn),生成了帶有緩存的代理類。其他類想調(diào)用這個(gè)類的緩存方法時(shí),會(huì)去調(diào)用這個(gè)代理類的方法,實(shí)現(xiàn)緩存功能。但是類內(nèi)部調(diào)用這個(gè)方法,就不會(huì)去調(diào)用代理類的方法,導(dǎo)致緩存失效
到此這篇關(guān)于Spring中的@Cacheable緩存注解詳解的文章就介紹到這了,更多相關(guān)Spring @Cacheable緩存注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot整合單機(jī)緩存ehcache的實(shí)現(xiàn)
- SpringBoot中整合Ehcache實(shí)現(xiàn)熱點(diǎn)數(shù)據(jù)緩存的詳細(xì)過程
- SpringBoot?Cache?二級(jí)緩存的使用
- 詳解如何使用SpringBoot的緩存@Cacheable
- Spring中緩存注解@Cache的使用詳解
- SpringCache緩存處理詳解
- 詳解Springboot @Cacheable 注解(指定緩存位置)
- Spring Cache @Cacheable 緩存在部分Service中不生效的解決辦法
- Springboot使用@Cacheable注解實(shí)現(xiàn)數(shù)據(jù)緩存
- SpringBoot使用Spring?Cache高效處理緩存數(shù)據(jù)
相關(guān)文章
Spring Boot配置線程池拒絕策略的場(chǎng)景分析(妥善處理好溢出的任務(wù))
本文通過實(shí)例代碼給大家介紹下如何為線程池配置拒絕策略、如何自定義拒絕策略。對(duì)Spring Boot配置線程池拒絕策略的相關(guān)知識(shí)感興趣的朋友一起看看吧2021-09-09SpringBoot集成Mybatis-Plus多租戶架構(gòu)實(shí)現(xiàn)
本文主要介紹了SpringBoot集成Mybatis-Plus多租戶架構(gòu)實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09SpringBoot中自定義注解實(shí)現(xiàn)控制器訪問次數(shù)限制實(shí)例
本篇文章主要介紹了SpringBoot中自定義注解實(shí)現(xiàn)控制器訪問次數(shù)限制實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04ReentrantLock條件變量使多個(gè)線程順序執(zhí)行
這篇文章主要為大家介紹了ReentrantLock條件變量使多個(gè)線程順序執(zhí)行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java中的HashSet集合存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)詳解
這篇文章主要介紹了Java中的HashSet集合存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)詳解,數(shù)組結(jié)構(gòu)他把元素進(jìn)行分組,相同哈希值的元素是一組,鏈表/紅黑樹結(jié)構(gòu)把相同哈希值的元素鏈接到一起,存儲(chǔ)數(shù)據(jù)到集合中,先計(jì)算元素的哈希值,需要的朋友可以參考下2023-09-09