緩存命中率
即從緩存中讀取數(shù)據(jù)的次數(shù) 與 總讀取次數(shù)的比率,命中率越高越好:
命中率 = 從緩存中讀取次數(shù) / (總讀取次數(shù)[從緩存中讀取次數(shù) + 從慢速設(shè)備上讀取的次數(shù)])
Miss率 = 沒有從緩存中讀取的次數(shù) / (總讀取次數(shù)[從緩存中讀取次數(shù) + 從慢速設(shè)備上讀取的次數(shù)])
這是一個非常重要的監(jiān)控指標(biāo),如果做緩存一定要健康這個指標(biāo)來看緩存是否工作良好;
移除策略
移除策略(Eviction policy),即如果緩存滿了,從緩存中移除數(shù)據(jù)的策略;常見的有LFU、LRU、FIFO。
FIFO(First In First Out):先進先出算法,即先放入緩存的先被移除;
LRU(Least Recently Used):最久未使用算法,使用時間距離現(xiàn)在最久的那個被移除;
LFU(Least Frequently Used):最近最少使用算法,一定時間段內(nèi)使用次數(shù)(頻率)最少的那個被移除;
TTL(Time To Live )
存活期,即從緩存中創(chuàng)建時間點開始直到它到期的一個時間段(不管在這個時間段內(nèi)有沒有訪問都將過期)
TTI(Time To Idle)
空閑期,即一個數(shù)據(jù)多久沒被訪問將從緩存中移除的時間。
自Spring 3.1起,提供了類似于@Transactional注解事務(wù)的注解Cache支持,且提供了Cache抽象;在此之前一般通過AOP實現(xiàn);使用Spring Cache的好處:
- 提供基本的Cache抽象,方便切換各種底層Cache;
- 通過注解Cache可以實現(xiàn)類似于事務(wù)一樣,緩存邏輯透明的應(yīng)用到我們的業(yè)務(wù)代碼上,且只需要更少的代碼就可以完成;
- 提供事務(wù)回滾時也自動回滾緩存;
- 支持比較復(fù)雜的緩存邏輯;
Cache
Spring提供的核心Cache接口,提供了緩存操作的讀取/寫入/移除方法;

public interface Cache {
String getName(); //緩存的名字
Object getNativeCache(); //得到底層使用的緩存,如Ehcache
ValueWrapper get(Object key); //根據(jù)key得到一個ValueWrapper,然后調(diào)用其get方法獲取值
<T> T get(Object key, Class<T> type);//根據(jù)key,和value的類型直接獲取value
void put(Object key, Object value);//往緩存放數(shù)據(jù)
void evict(Object key);//從緩存中移除key對應(yīng)的緩存
void clear(); //清空緩存
interface ValueWrapper { //緩存值的Wrapper
Object get(); //得到真實的value
}
}
CacheManager
因為我們在應(yīng)用中并不是使用一個Cache,而是多個,因此Spring還提供了CacheManager抽象,用于緩存的管理
public interface CacheManager {
Cache getCache(String name); //根據(jù)Cache名字獲取Cache
Collection<String> getCacheNames(); //得到所有Cache的名字
}

除了GuavaCacheManager之外,其他Cache都支持Spring事務(wù)的,即如果事務(wù)回滾了,Cache的數(shù)據(jù)也會移除掉。
Spring不進行Cache的緩存策略的維護,這些都是由底層Cache自己實現(xiàn),Spring只是提供了一個Wrapper,提供一套對外一致的API。
Cache注解
- @EnableCaching
- @CachePut
public @interface CachePut {
String[] value(); //緩存的名字,可以把數(shù)據(jù)寫到多個緩存
String key() default ""; //緩存key,如果不指定將使用默認的KeyGenerator生成,后邊介紹
String condition() default ""; //滿足緩存條件的數(shù)據(jù)才會放入緩存,condition在調(diào)用方法之前和之后都會判斷
String unless() default ""; //用于否決緩存更新的,不像condition,該表達只在方法執(zhí)行之后判斷,此時可以拿到返回值result進行判斷了
}
- @CacheEvict
public @interface CacheEvict {
String[] value(); //請參考@CachePut
String key() default ""; //請參考@CachePut
String condition() default ""; //請參考@CachePut
boolean allEntries() default false; //是否移除所有數(shù)據(jù)
boolean beforeInvocation() default false;//是調(diào)用方法之前移除/還是調(diào)用之后移除
- @Cacheable
應(yīng)用到讀取數(shù)據(jù)的方法上,即可緩存的方法,如查找方法:先從緩存中讀取,如果沒有再調(diào)用方法獲取數(shù)據(jù),然后把數(shù)據(jù)添加到緩存中:
public @interface Cacheable {
String[] value(); //請參考@CachePut
String key() default ""; //請參考@CachePut
String condition() default "";//請參考@CachePut
String unless() default ""; //請參考@CachePut
}
- @Caching
public @interface Caching {
Cacheable[] cacheable() default {}; //聲明多個@Cacheable
CachePut[] put() default {}; //聲明多個@CachePut
CacheEvict[] evict() default {}; //聲明多個@CacheEvict
}
提供的SpEL上下文數(shù)據(jù)
Spring Cache提供了一些供我們使用的SpEL上下文數(shù)據(jù)

Key生成器
如果在Cache注解上沒有指定key的話@CachePut(value = "user"),會使用KeyGenerator進行生成一個key:
條件緩存
根據(jù)運行流程,如下@Cacheable將在執(zhí)行方法之前( #result還拿不到返回值)判斷condition,如果返回true,則查緩存;