緩存簡(jiǎn)介
工作機(jī)制是:先從緩存中讀取數(shù)據(jù)去枷,如果沒有再從慢速設(shè)備上讀取實(shí)際數(shù)據(jù)(數(shù)據(jù)也會(huì)存入緩存);緩存什么:那些經(jīng)常讀取且不經(jīng)常修改的數(shù)據(jù)/那些昂貴(CPU/IO)的且對(duì)于相同的請(qǐng)求有相同的計(jì)算結(jié)果的數(shù)據(jù)。例如Maven/京東物流都是這種思想
緩存命中率
即從緩存中讀取數(shù)據(jù)的次數(shù) 與 總讀取次數(shù)的比率椎侠,命中率越高越好:
命中率 = 從緩存中讀取次數(shù) / (總讀取次數(shù)[從緩存中讀取次數(shù) + 從慢速設(shè)備上讀取的次數(shù)])
緩存策略
Eviction policy 移除策略姿染,即如果緩存滿了,從緩存中移除數(shù)據(jù)的策略勉痴;常見的有LFU赫模、LRU、FIFO:
FIFO(First In First Out):先進(jìn)先出算法蒸矛,即先放入緩存的先被移除瀑罗;
LRU(Least Recently Used):最久未使用算法,使用時(shí)間距離現(xiàn)在最久的那個(gè)被移除雏掠;
LFU(Least Frequently Used):最近最少使用算法斩祭,一定時(shí)間段內(nèi)使用次數(shù)(頻率)最少的那個(gè)被移除;
TTL(Time To Live )存活期乡话,即從緩存中創(chuàng)建時(shí)間點(diǎn)開始直到它到期的一個(gè)時(shí)間段(不管在這個(gè)時(shí)間段內(nèi)有沒有訪問都將過期)
TTI(Time To Idle)空閑期摧玫,即一個(gè)數(shù)據(jù)多久沒被訪問將從緩存中移除的時(shí)間。
spring定義了org.springframework.cache.CacheManager和org.springframework.cache.Cache接口來統(tǒng)一不同的緩存技術(shù),而SpringBoot為我們提供了自動(dòng)配置多個(gè)CacheManager的實(shí)現(xiàn)
EhCacheCacheConfiguration.class EhCache實(shí)現(xiàn)緩存
GuavaCacheConfiguration.class Guava實(shí)現(xiàn)緩存
JCacheCacheConfiguration.class JCache實(shí)現(xiàn)緩存
GenericCacheConfiguration.class Collection實(shí)現(xiàn)緩存
SimpleCacheConfiguration.class ConcurrentMap實(shí)現(xiàn)緩存
在不做任何額外配置的情況下绑青,默認(rèn)使用SimpleCacheConfiguration诬像,即ConcurrentMapCacheManager。Springboot支持以“spring.cache”為前綴的屬性來配置闸婴,如:
spring.cache.type=#ehcache,generic,redis,jcache等
spring.cache.cache-names=#緩存名稱
spring.cache.ehcache.config= #ehcache配置文件地址
在Spring Boot中通過@EnableCaching注解自動(dòng)化配置合適的緩存管理器(CacheManager)颅停,Spring Boot根據(jù)下面的順序去偵測(cè)緩存提供者:
Generic
JCache (JSR-107)
EhCache 2.x
Hazelcast
Infinispan
Redis
Guava
Simple
除了按順序偵測(cè)外,我們也可以通過配置屬性spring.cache.type來強(qiáng)制指定掠拳。我們可以通過debug調(diào)試查看cacheManager對(duì)象的實(shí)例來判斷當(dāng)前使用了什么緩存癞揉。
默認(rèn)的ConcurrentMapCacheManager使用步驟:
1. 引入pom.xml
org.springframework.boot
spring-boot-starter-cache
2. 在主類或configuration類中通過 @EnableCaching 開啟緩存
3. @Cacheable 查詢,首先檢查緩存是否存在,如果有則直接從緩存取然后返回喊熟,若沒有則查DB柏肪,并將結(jié)果(有值或空)添加數(shù)據(jù)到緩存中。緩存名稱為people芥牌,緩存key為person的id屬性
參數(shù):
value烦味、cacheNames:兩個(gè)等同的參數(shù)(cacheNames為Spring 4新增,作為value的別名)壁拉,用于指定緩存存儲(chǔ)的集合名谬俄。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必須有的value屬性弃理,也成為非必需項(xiàng)了
key:緩存對(duì)象存儲(chǔ)在Map集合中的key值溃论,非必需,缺省按照函數(shù)的所有參數(shù)組合作為key值痘昌,若自己配置需使用SpEL表達(dá)式钥勋,比如:@Cacheable(key = "#p0"):使用函數(shù)第一個(gè)參數(shù)作為緩存的key值,更多關(guān)于SpEL表達(dá)式的詳細(xì)內(nèi)容可參考官方文檔
condition:緩存對(duì)象的條件辆苔,非必需算灸,也需使用SpEL表達(dá)式,只有滿足表達(dá)式條件的內(nèi)容才會(huì)被緩存驻啤,默認(rèn)緩存所有結(jié)果數(shù)據(jù)菲驴。比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有當(dāng)?shù)谝粋€(gè)參數(shù)的長(zhǎng)度小于3的時(shí)候才會(huì)被緩存骑冗,若做此配置上面的AAA用戶就不會(huì)被緩存赊瞬。
4. @CachePut 插入或更新到DB后,檢查緩存中是否有該key沐旨,有則更新森逮,沒有則新增榨婆。新增或更新的內(nèi)容為接口的返回值磁携,所以保存/更新接口必須有返回值。 若返回值為空良风,則緩存也會(huì)為空值谊迄。
參數(shù):同上
5. @CacheEvict 表示從緩存people中刪除key為id的數(shù)據(jù)
參數(shù):除上述之外,還有2個(gè)烟央。
allEntries:非必需统诺,默認(rèn)為false。當(dāng)為true時(shí)疑俭,會(huì)移除所有數(shù)據(jù)
beforeInvocation:非必需粮呢,默認(rèn)為false,會(huì)在調(diào)用方法之后移除數(shù)據(jù)。當(dāng)為true時(shí)啄寡,會(huì)在調(diào)用方法之前移除數(shù)據(jù)豪硅。
ehcache使用步驟:
1. pom.xml引入依賴:
net.sf.ehcache
ehcache
2.8.3
2. 在src/main/resources目錄下創(chuàng)建:ehcache.xml
xsi:noNamespaceSchemaLocation="ehcache.xsd">
maxEntriesLocalHeap="200"
timeToLiveSeconds="600">
或配置
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:config/another-config.xml
redis使用步驟:
1. pom.xml引入依賴:
org.springframework.boot
spring-boot-starter-redis
2. properties中配置redis端口等
3. 配置RedisCacheManager,RedisTemplate的bean挺物,具體參考源碼
綜合說明:
1. spring cache是spring3.1就有的概念懒浮,通過AOP實(shí)現(xiàn),提供注解方式识藤,但由于是進(jìn)程內(nèi)的緩存砚著,適合于單機(jī),分布式環(huán)境下不適用痴昧。EhCache提供了集群環(huán)境下的緩存同步策略稽穆,但是同步依然需要一定的時(shí)間,短暫的緩存不一致依然存在剪个。在一些要求高一致性(任何數(shù)據(jù)變化都能及時(shí)的被查詢到)的系統(tǒng)和應(yīng)用中秧骑,就不能再使用EhCache來解決了,這個(gè)時(shí)候使用集中式緩存是個(gè)不錯(cuò)的選擇
2. redis是集中式緩存扣囊,通過上述注解方式使用redisCacheManager乎折,則緩存數(shù)據(jù)存儲(chǔ)在redis,保證分布式環(huán)境數(shù)據(jù)一致性侵歇。
實(shí)例源碼:?test1-cache