Java高性能本地緩存框架Caffeine的實(shí)現(xiàn)
一、序言
Caffeine是一個(gè)進(jìn)程內(nèi)部緩存框架,使用了Java 8最新的[StampedLock]樂(lè)觀鎖技術(shù),極大提高緩存并發(fā)吞吐量,一個(gè)高性能的 Java 緩存庫(kù),被稱(chēng)為最快緩存。
二、緩存簡(jiǎn)介
(一)緩存對(duì)比
從橫向?qū)ΤS玫木彺孢M(jìn)行對(duì)比,有助于加深對(duì)緩存的理解,有助于提高技術(shù)選型的合理性。下面對(duì)比三種常用緩存:Redis、EhCache、Caffeine。
1、序列化
緩存 | 序列化 | 原因 |
---|---|---|
Redis | 必須實(shí)現(xiàn)序列化 | 進(jìn)程間數(shù)據(jù)傳輸,因此必須實(shí)現(xiàn)序列化。大多數(shù)情況下涉及內(nèi)網(wǎng)網(wǎng)絡(luò)傳輸;作為緩存數(shù)據(jù)庫(kù)使用,持久化是標(biāo)配。 |
EhCache | 不一定需要實(shí)現(xiàn)序列化 | 當(dāng)緩存配置不持久化到磁盤(pán)時(shí),無(wú)需實(shí)現(xiàn)序列化接口。使用時(shí),如果不確定是否需要持久化到磁盤(pán),建議統(tǒng)一實(shí)現(xiàn)序列化接口。 |
Caffeine | 不需要實(shí)現(xiàn)序列化 | Map對(duì)象的改進(jìn)型接口,不涉及任何形式的網(wǎng)絡(luò)傳輸和持久化,因此完全不需要實(shí)現(xiàn)序列化接口。 |
2、進(jìn)程關(guān)系
緩存 | 進(jìn)程關(guān)系 | 備注 |
---|---|---|
Redis | 與業(yè)務(wù)進(jìn)程獨(dú)立,由操作系統(tǒng)獨(dú)立管理,業(yè)務(wù)系統(tǒng)重啟對(duì)緩存服務(wù)無(wú)影響 | Redis服務(wù)與業(yè)務(wù)服務(wù)獨(dú)立,互相影響較小 |
EhCache | 附著于業(yè)務(wù)進(jìn)程,業(yè)務(wù)系統(tǒng)重啟,存儲(chǔ)與內(nèi)存部分的緩存數(shù)據(jù)丟失;存儲(chǔ)與硬盤(pán)部分的數(shù)據(jù)繼續(xù)存在 | 緩存配置存在兩種模式:一種是純內(nèi)存型,一種是可持久化到磁盤(pán) |
Caffeine | 附著于業(yè)務(wù)進(jìn)程,業(yè)務(wù)系統(tǒng)重啟,緩存數(shù)據(jù)全部丟失 | 純內(nèi)存型 |
內(nèi)存型緩存的理解:緩存都是使用內(nèi)存作為存儲(chǔ)媒介的,各種緩存服務(wù)的區(qū)別如下:Caffeine是內(nèi)存型緩存是指緩存與調(diào)用者屬于同一個(gè)應(yīng)用,準(zhǔn)確的說(shuō)屬于同一個(gè)JVM;Redis是指另外一個(gè)獨(dú)立進(jìn)程的內(nèi)存型,緩存數(shù)據(jù)存儲(chǔ)在Redis數(shù)據(jù)庫(kù)的內(nèi)存中,而不是在調(diào)用服務(wù)所屬的內(nèi)存中。
(二)本地緩存
本地緩存與分布式緩存對(duì)應(yīng),緩存進(jìn)程和應(yīng)用進(jìn)程同屬于一個(gè)JVM,數(shù)據(jù)的讀、寫(xiě)在一個(gè)進(jìn)程內(nèi)完成。本地緩存沒(méi)有網(wǎng)絡(luò)開(kāi)銷(xiāo),訪問(wèn)速度很快。
Caffeine是基于Guava Cache增強(qiáng)的新一代緩存技術(shù),緩存性能極其出色。
1、Map
JDK內(nèi)置的Map可作為緩存的一種實(shí)現(xiàn)方式,然而嚴(yán)格意義來(lái)講,其不能算作緩存的范疇。原因如下:一是其存儲(chǔ)的數(shù)據(jù)不能主動(dòng)過(guò)期;二是無(wú)任何緩存淘汰策略。
三、SpringCache
Caffeine作為Spring體系中內(nèi)置的緩存之一,Spring Cache同樣提供調(diào)用接口支持。
(一)需求分析
1、CacheManager
Caffeine屬于進(jìn)程內(nèi)部緩存框架,不需要配置多數(shù)據(jù)源,因此一個(gè)CacheManager
即可滿(mǎn)足需求。如果應(yīng)用中僅使用Caffeine作為唯一的緩存框架,那么通過(guò)注解使用時(shí)無(wú)需顯式指明。
2、CacheName
任何一類(lèi)緩存,不同業(yè)務(wù)模塊間緩存過(guò)期時(shí)間以及緩存淘汰策略幾乎不相同,因此應(yīng)該支持多CacheName,并且應(yīng)該具有不同配置。過(guò)期時(shí)間是不同CacheName間緩存配置的重要區(qū)別。
3、Key
內(nèi)存型緩存,無(wú)可視化界面,因此首要滿(mǎn)足鍵值的唯一性,鍵值唯一是正確使用業(yè)務(wù)緩存的基礎(chǔ)保證。
(二)序列化
Caffeine緩存不涉及任何序列化,因此目標(biāo)緩存對(duì)象不需要實(shí)現(xiàn)Serializable
接口。若涉及多級(jí)緩存或者多種緩存共用,其它需要網(wǎng)絡(luò)傳輸或者持久化的緩存需要序列化,Caffeine盡管也使用實(shí)現(xiàn)序列化的實(shí)體類(lèi),但是不做序列化操作。
不需要序列化,降低了緩存使用難度。
(三)集成
1、引入依賴(lài)
如果無(wú)特別要求,使用較新SpringBoot的內(nèi)置版本即可。
<dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency>
2、全局配置
全局配置中指定使用caffeine
緩存管理。
spring: cache: type: caffeine
3、緩存管理器
配置緩存管理器:多CacheName配置。
public interface CacheNameTimeConstant { String CACHE_DEFAULT = "CACHE_DEFAULT"; String CACHE_10SECS = "CACHE_10SECS"; String CACHE_60SECS = "CACHE_60SECS"; }
同一個(gè)CacheManager配置多個(gè)CacheName,此處僅配置過(guò)期時(shí)間的差異,其余配置可自由增加。
@Bean public CacheManager caffeineCacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); List<CaffeineCache> caches = new ArrayList<>(); caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_5SECS, Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build())); caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_10SECS, Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build())); caches.add(new CaffeineCache(CacheNameTimeConstant.CACHE_30SECS, Caffeine.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build())); cacheManager.setCaches(caches); return cacheManager; }
四、小結(jié)
Java領(lǐng)域可用的緩存框架非常多,Caffeine
不屬于分布式緩存,但不影響其在本地緩存場(chǎng)景出色的表現(xiàn)。開(kāi)發(fā)者在進(jìn)行緩存架構(gòu)設(shè)計(jì)時(shí)需要綜合考慮各類(lèi)緩存的優(yōu)缺點(diǎn),依據(jù)具體場(chǎng)景選配相應(yīng)緩存。
到此這篇關(guān)于Java高性能本地緩存框架Caffeine的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java Caffeine內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
從入門(mén)到精通:Java List遍歷修改的完全指南
在Java中,我們經(jīng)常需要遍歷List集合并對(duì)其中的元素進(jìn)行修改,這可以通過(guò)使用迭代器或for循環(huán)來(lái)實(shí)現(xiàn),需要的朋友可以參考下2023-10-10如何在Spring?Boot中使用OAuth2認(rèn)證和授權(quán)
這篇文章主要介紹了如何在Spring?Boot中使用OAuth2認(rèn)證和授權(quán)的相關(guān)資料,OAuth2.0是一種開(kāi)放的授權(quán)協(xié)議,它允許用戶(hù)授權(quán)第三方應(yīng)用訪問(wèn)其賬戶(hù)(或資源),而無(wú)需共享其用戶(hù)賬戶(hù)憑據(jù),需要的朋友可以參考下2023-12-12淺談利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問(wèn)題
本篇文章主要介紹了淺談利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問(wèn)題,具有一定的參考價(jià)值,有需要的可以了解一下2017-08-0823種設(shè)計(jì)模式(16)java訪問(wèn)者模式
這篇文章主要為大家詳細(xì)介紹了23種設(shè)計(jì)模式之java訪問(wèn)者模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

簡(jiǎn)單了解java類(lèi)的初始化以及類(lèi)的實(shí)例化

SpringBoot項(xiàng)目讀取外置logback配置文件的問(wèn)題及解決