您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring內存緩存Caffeine如何使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring內存緩存Caffeine如何使用”吧!
依賴
首先搭建一個標準的SpringBoot項目工程,相關版本以及依賴如下
本項目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
進行開發
<dependencies> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> </dependencies>
引入上面的jar包之后,就可以進入caffeine的使用環節了;我們主要依照官方wiki來進行演練
Home zh CN · ben-manes/caffeine Wiki
caffeine提供了四種緩存策略,主要是基于手動添加/自動添加,同步/異步來進行區分
其基本使用姿勢于Guava差不多
private LoadingCache<String, Integer> autoCache; private AtomicInteger idGen; public CacheService() { // 手動緩存加載方式 idGen = new AtomicInteger(100); uidCache = Caffeine.newBuilder() // 設置寫入后五分鐘失效 .expireAfterWrite(5, TimeUnit.MINUTES) // 設置最多的緩存數量 .maximumSize(100) .build(); }
1.1 三種失效策略
注意參數設置,我們先看一下失效策略,共有下面幾種
權重:
maximumSize: 基于容量策略,當緩存內元素個數超過時,通過基于就近度和頻率的算法來驅逐掉不會再被使用到的元素
maximumWeight: 基于權重的容量策略,主要應用于緩存中的元素存在不同的權重場景
時間:
expireAfterAccess: 基于訪問時間
expireAfterWrite: 基于寫入時間
expireAfter: 可以根據讀更新寫入來調整有效期
引用:
weakKeys: 保存的key為弱引用
weakValues: 保存的value會使用弱引用
softValues: 保存的value使用軟引用
弱引用:這允許在GC的過程中,當沒有被任何強引用指向的時候去將緩存元素回收
軟引用:在GC過程中被軟引用的對象將會被通過LRU算法回收
1.2 緩存增刪查姿勢
接下來我們看一下手動方式的使用
public void getUid(String session) { // 重新再取一次,這次應該就不是重新初始化了 Integer uid = uidCache.getIfPresent(session); System.out.println("查看緩存! 當沒有的時候返回的是 uid: " + uid); // 第二個參數表示當不存在時,初始化一個,并寫入緩存中 uid = uidCache.get(session, (key) -> 10); System.out.println("初始化一個之后,返回的是: " + uid); // 移除緩存 uidCache.invalidate(session); // 手動添加一個緩存 uidCache.put(session + "_2", 11); // 查看所有的額緩存 Map map = uidCache.asMap(); System.out.println("total: " + map); // 干掉所有的緩存 uidCache.invalidateAll(); }
查詢緩存&添加緩存
getIfPresent(key)
: 不存在時,返回null
get(key, (key) -> {value初始化策略})
: 不存在時,會根據第二個lambda表達式來寫入數據,這個就表示的是手動加載緩存
asMap
: 獲取緩存所有數據
添加緩存
put(key, val)
: 主動添加緩存
清空緩存
invalidate
: 主動移除緩存
invalidateAll
: 失效所有緩存
執行完畢之后,輸出日志:
查看緩存! 當沒有的時候返回的是 uid: null
初始化一個之后,返回的是: 10
total: {02228476-bcd9-412d-b437-bf0092c4a5f6_2=11}
在創建的時候,就指定緩存未命中時的加載規則
// 在創建時,自動指定加載規則 private LoadingCache<String, Integer> autoCache; private AtomicInteger idGen; public CacheService() { // 手動緩存加載方式 idGen = new AtomicInteger(100); autoCache = Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(100) .build(new CacheLoader<String, Integer>() { @Override public @Nullable Integer load(@NonNull String key) throws Exception { return idGen.getAndAdd(1); } }); }
它的配置,與前面介紹的一致;主要的區別點在于build時,確定緩存值的獲取方式
2.1 緩存使用姿勢
public void autoGetUid(String session) { Integer uid = autoCache.getIfPresent(session); System.out.println("自動加載,沒有時返回: " + uid); uid = autoCache.get(session); System.out.println("自動加載,沒有時自動加載一個: " + uid); // 批量查詢 List<String> keys = Arrays.asList(session, session + "_1"); Map<String, Integer> map = autoCache.getAll(keys); System.out.println("批量獲取,一個存在一個不存在時:" + map); // 手動加一個 autoCache.put(session + "_2", 11); Map total = autoCache.asMap(); System.out.println("total: " + total); }
與前面的區別在于獲取緩存值的方式
get(key): 不用傳第二個參數,直接傳key獲取對應的緩存值,如果沒有自動加載數據
getAll(keys): 可以批量獲取數據,若某個key不再緩存中,會自動加載;在里面的則直接使用緩存的
實際輸出結果如下
自動加載,沒有時返回: null
自動加載,沒有時自動加載一個: 100
批量獲取,一個存在一個不存在時:{02228476-bcd9-412d-b437-bf0092c4a5f6=100, 02228476-bcd9-412d-b437-bf0092c4a5f6_1=101}
total: {02228476-bcd9-412d-b437-bf0092c4a5f6_2=11, 02228476-bcd9-412d-b437-bf0092c4a5f6_1=101, 02228476-bcd9-412d-b437-bf0092c4a5f6=100}
異步,主要是值在獲取換粗內容時,采用的異步策略;使用與前面沒有什么太大差別
// 手動異步加載緩存 private AsyncCache<String, Integer> asyncUidCache; public CacheService() { asyncUidCache = Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(100) .buildAsync(); }
3.1 緩存使用姿勢
public void asyncGetUid(String session) throws ExecutionException, InterruptedException { // 重新再取一次,這次應該就不是重新初始化了 CompletableFuture<Integer> uid = asyncUidCache.getIfPresent(session); System.out.println("查看緩存! 當沒有的時候返回的是 uid: " + (uid == null ? "null" : uid.get())); // 第二個參數表示當不存在時,初始化一個,并寫入緩存中 uid = asyncUidCache.get(session, (key) -> 10); System.out.println("初始化一個之后,返回的是: " + uid.get()); // 手動塞入一個緩存 asyncUidCache.put(session + "_2", CompletableFuture.supplyAsync(() -> 12)); // 移除緩存 asyncUidCache.synchronous().invalidate(session); // 查看所有的額緩存 System.out.println("print total cache:"); for (Map.Entry<String, CompletableFuture<Integer>> sub : asyncUidCache.asMap().entrySet()) { System.out.println(sub.getKey() + "==>" + sub.getValue().get()); } System.out.println("total over"); }
getIfPresent: 存在時返回CompletableFuture,不存在時返回null,因此注意npe的問題
get(key, Function<>): 第二個參數表示加載數據的邏輯
put(key, CompletableFuture<>): 手動加入緩存,注意這里也不是直接加一個具體的value到緩存
synchronous().invalidate() : 同步清除緩存
getAll: 一次獲取多個緩存,同樣的是在緩存的取緩存,不在的根據第二個傳參進行加載
與前面相比,使用姿勢差不多,唯一注意的是,獲取的并不是直接的結果,而是CompletableFuture,上面執行之后的輸出如下:
查看緩存! 當沒有的時候返回的是 uid: null
初始化一個之后,返回的是: 10
print total cache:
5dd53310-aec7-42a5-957e-f7492719c29d_2==>12
total over
在定義緩存時,就指定了緩存不存在的加載邏輯;與第二個相比區別在于這里是異步加載數據到緩存中
private AtomicInteger idGen; // 自動異步加載緩存 private AsyncLoadingCache<String, Integer> asyncAutoCache; public CacheService() { idGen = new AtomicInteger(100); asyncAutoCache = Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(100) .buildAsync(new CacheLoader<String, Integer>() { @Override public @Nullable Integer load(@NonNull String key) throws Exception { return idGen.getAndAdd(1); } }); }
4.1 緩存使用姿勢
public void asyncAutoGetUid(String session) { try { CompletableFuture<Integer> uid = asyncAutoCache.getIfPresent(session); System.out.println("自動加載,沒有時返回: " + (uid == null ? "null" : uid.get())); uid = asyncAutoCache.get(session); System.out.println("自動加載,沒有時自動加載一個: " + uid.get()); // 批量查詢 List<String> keys = Arrays.asList(session, session + "_1"); CompletableFuture<Map<String, Integer>> map = asyncAutoCache.getAll(keys); System.out.println("批量獲取,一個存在一個不存在時:" + map.get()); // 手動加一個 asyncAutoCache.put(session + "_2", CompletableFuture.supplyAsync(() -> 11)); // 查看所有的額緩存 System.out.println("print total cache:"); for (Map.Entry<String, CompletableFuture<Integer>> sub : asyncAutoCache.asMap().entrySet()) { System.out.println(sub.getKey() + "==>" + sub.getValue().get()); } System.out.println("total over"); // 清空所有緩存 asyncAutoCache.synchronous().invalidateAll(); } catch (Exception e) { e.printStackTrace(); } }
輸出:
自動加載,沒有時返回: null
自動加載,沒有時自動加載一個: 102
批量獲取,一個存在一個不存在時:{5dd53310-aec7-42a5-957e-f7492719c29d=102, 5dd53310-aec7-42a5-957e-f7492719c29d_1=103}
print total cache:
5dd53310-aec7-42a5-957e-f7492719c29d_2==>11
5dd53310-aec7-42a5-957e-f7492719c29d_1==>103
5dd53310-aec7-42a5-957e-f7492719c29d==>102
total over
感謝各位的閱讀,以上就是“Spring內存緩存Caffeine如何使用”的內容了,經過本文的學習后,相信大家對Spring內存緩存Caffeine如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。