Spring Cache是什麼?
Spring Cache 是一個非常優秀的緩存元件。自Spring 3.1起,提供了類似于@Transactional注解事務的注解Cache支援,且提供了Cache抽象,友善切換各種底層Cache(如:redis)
Spring Cache的好處
1,提供基本的Cache抽象,友善切換各種底層Cache;
2,通過注解Cache可以實作類似于事務一樣,緩存邏輯透明的應用到我們的業務代碼上,且隻需要更少的代碼就可以完成;
3,提供事務復原時也自動復原緩存;
4,支援比較複雜的緩存邏輯;
Spring Cache支援的緩存類型
@Bean
public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
return new EhCacheCacheManager(ehCacheCacheManager);
}
Spring Cache常用的緩存注釋
@EnableCaching:
标記注解 @EnableCaching,開啟緩存,并配置Redis緩存管理器。@EnableCaching 注釋觸發後置處理器,檢查每一個Spring bean 的 public 方法是否存在緩存注解。如果找到這樣的一個注釋,
自動建立一個代理攔截方法調用和處理相應的緩存行為。
緩存@Cacheable
根據方法對其傳回結果進行緩存,下次請求時,如果緩存存在,則直接讀取緩存資料傳回;如果緩存不存在,則執行方法,并把傳回的結果存入緩存中。一般用在查詢方法上。
屬性值如下:
緩存@CachePut
使用該注解标志的方法,每次都會執行,并将結果存入指定的緩存中。其他方法可以直接從響應的緩存中讀取緩存資料,而不需要再去查詢資料庫。一般用在新增方法上。
緩存@CacheEvict
緩存應用流程
- 通過緩存提供者CachingProvider得到緩存管理器CacheManager;
- 緩存提供者可以管理多個緩存管理器;
- 每個緩存管理器管理特定類型的緩存;比如:CacheManager1管理redis緩存、CacheManager2管理memcache緩存;
- 緩存管理器用來管理緩存Cache;
- 一個緩存管理器管理多個緩存;比如:Cache1用來儲存員工資料、Cache2用來緩存部門資料;
- 緩存中儲存多條資料,每一條資料是一個鍵值對;
- Cache接口中提供了一些api,用來對資料進行增删改查操作;
什麼樣的資料适合放入緩存
什麼樣的資料需要放進緩存呢?把資料放入緩存,有三個标準:
- 資料量不大
- 通路頻率高
- 資料更改頻率低
常用的本地緩存
本地緩存 | 介紹 |
Caffeine | 是使用 對 緩存的重寫版本,在 中将取代 ,基于 算法實作,支援多種緩存過期政策。 |
ehcache | 是一個純 的程序内緩存架構,具有快速、精幹等特點,是 中預設的 。 |
GuavaCache | 工具包中的一個非常友善易用的本地化緩存實作,基于 算法實作,支援多種緩存過期政策。 |
常用的本地緩存測試比較
測試邏輯:
- 建構Cache,load方法為簡單的字元串拼接
- 将250000個字元串加載到cache後,啟動任務線程,預熱10s後,開始計時,統計每10秒的count,共6輪,最後統計每輪中的每秒平均值
測試結果:
(1) 6個線程純讀:
(2) 4個線程讀+2個線程寫:
壓測對比
運作環境:MacBook
Pro i7-4870HQ CPU @ 2.50GHz (4 core) 16 GB
讀操作
在這個基準測試中,8個線程同時從配置了最大大小的緩存中讀取。
寫操作
在這個基準測試中,8個線程同時寫入一個配置了最大大小的緩存。
讀
Unbounded | ops/s (8 threads) | ops/s (16 threads) |
ConcurrentHashMap (v8) | 560,367,163 | 1,171,389,095 |
ConcurrentHashMap (v7) | 301,331,240 | 542,304,172 |
Bounded | ||
Caffeine | 181,703,298 | 382,355,194 |
ConcurrentLinkedHashMap | 154,771,582 | 313,892,223 |
LinkedHashMap_Lru | 9,209,065 | 13,598,576 |
Guava (default) | 12,434,655 | 10,647,238 |
Guava (64) | 24,533,922 | 43,101,468 |
Ehcache2_Lru | 11,252,172 | 20,750,543 |
Ehcache3_Lru | 11,415,248 | 17,611,169 |
Infinispan_Old_Lru | 29,073,439 | 49,719,833 |
Infinispan_New_Lru | 4,888,027 | 4,749,506 |
寫
Unbounded | ops/s (8 threads) | ops/s (16 threads) |
ConcurrentHashMap (v8) | 60,477,550 | 50,591,346 |
ConcurrentHashMap (v7) | 46,204,091 | 36,659,485 |
Bounded | ||
Caffeine | 55,281,751 | 48,295,360 |
ConcurrentLinkedHashMap | 23,819,597 | 39,797,969 |
LinkedHashMap_Lru | 10,179,891 | 10,859,549 |
Guava (default) | 4,764,056 | 5,446,282 |
Guava (64) | 8,128,024 | 7,483,986 |
Ehcache2_Lru | 4,205,936 | 4,697,745 |
Ehcache3_Lru | 10,051,020 | 13,939,317 |
Infinispan_Old_Lru | 7,538,859 | 7,332,973 |
Infinispan_New_Lru | 4,797,502 | 5,086,305 |
本地緩存推薦
Caffeine是在guava基礎上進行優化的産物,也是帶着替代guava的目的而來的,因而在使用上差别不大,但是通過測試可以明顯看到Caffeine在性能上的優勢。
Caffeine是Spring 5預設支援的Cache,可見Spring對它的看重。
Caffine是什麼?
Caffeine是⼀個基于Java
8的⾼性能,接近最佳的緩存庫。
Caffine有什麼特⾊?
- ⾃動将條⽬加載到緩存中,可選擇異步加載
- 基于頻率和新近度超過最⼤值時的基于⼤⼩的驅逐
- ⾃上次通路或上次寫⼊以來測量的條⽬的基于時間的到期
- 當第⼀個條⽬的陳舊請求發⽣時,異步重新整理
- 密鑰⾃動包含在弱引⽤中
- 值⾃動包含在弱引⽤或軟引⽤中
- 被驅逐(或以其他⽅式删除)條⽬的通知
- 寫⼊傳播到外部資源
- 累積緩存通路統計資訊