我們的項目引入本地緩存無冕之王—Caffeine
前言
大家好,我是田螺。
最近給我的知識星球手把手書城系統(tǒng),引入了Caffeine本地緩存。看網(wǎng)上評價,它居然被稱為本地緩存無冕之王,本文給大家簡單介紹一下它吧~~
- Caffeine 是什么?
- Caffeine的優(yōu)點與缺點
- 實際業(yè)務(wù)的使用場景
- 使用Caffeine需要注意的問題
- Caffeine與Redis的區(qū)別及選擇
- 代碼實踐實現(xiàn)
1. Caffeine 是什么?
com.github.benmanes.caffeine.cache.Caffeine.Caffeine 是一個由Google開源的高性能Java本地緩存庫。它提供了靈活的配置選項和強(qiáng)大的緩存淘汰策略,旨在滿足現(xiàn)代應(yīng)用程序?qū)Φ脱舆t和高吞吐量的需求。Caffeine通過精細(xì)的鎖優(yōu)化和無鎖數(shù)據(jù)結(jié)構(gòu),實現(xiàn)了極高的并發(fā)性能。
簡單一句話概括,就是Caffeine是具有高性能的Java本地緩存庫。
2. Caffeine的優(yōu)點與缺點
優(yōu)點:
- 高性能:使用基于 ConcurrentHashMap 的非阻塞算法,保證了并發(fā)情況下的高性能。
- 靈活配置:支持多種緩存淘汰策略,如LRU、LFU等,并允許自定義緩存大小、過期時間等參數(shù)。
- 豐富的統(tǒng)計信息:內(nèi)置統(tǒng)計功能,幫助開發(fā)者深入了解緩存的行為,從而進(jìn)行針對性的優(yōu)化。
缺點:
- 本地緩存限制:由于Caffeine是本地緩存,因此無法跨進(jìn)程共享數(shù)據(jù),這在分布式系統(tǒng)中可能是一個限制。
- 僅適合短期緩存:不提供持久化機(jī)制,重啟后緩存會丟失。
- 緩存大小限制:Caffeine 適用于本地緩存場景,緩存大小受制于 JVM 可用內(nèi)存。
3. 實際業(yè)務(wù)的使用場景
有哪些場景適合使用它呢?
系統(tǒng)需要頻繁查的,數(shù)據(jù)變化頻率較低。
比如:
- 用戶信息緩存:將用戶的基本信息(如用戶名、角色、權(quán)限)緩存到本地。
- 配置項緩存:存儲系統(tǒng)的靜態(tài)配置信息(如字典表、產(chǎn)品分類信息)。
- 熱門內(nèi)容緩存:緩存熱門商品、推薦內(nèi)容或排行榜,避免頻繁從數(shù)據(jù)庫中讀取。
我們項目組,當(dāng)前實際開發(fā)的項目,產(chǎn)品配置參數(shù)表,就使用了本地緩存。
4. 使用Caffeine需要注意的問題
- 緩存一致性:在分布式系統(tǒng)中,需要確保多個節(jié)點之間的緩存一致性。
- 內(nèi)存管理:合理配置緩存大小和淘汰策略,避免內(nèi)存溢出和性能下降。同時,定期監(jiān)控緩存使用情況,及時調(diào)整配置。
- 緩存擊穿:對于某些熱點數(shù)據(jù),如果緩存失效且訪問量巨大,可能會導(dǎo)致數(shù)據(jù)庫壓力驟增??梢酝ㄟ^設(shè)置熱點數(shù)據(jù)的永不過期策略或使用互斥鎖來避免緩存擊穿。(如果只是單純用來做緩存配置表這些,則不用擔(dān)心這個問題)
5. Caffeine與Redis的區(qū)別及選擇
- 存儲位置:Caffeine是本地緩存,存儲在JVM內(nèi)存中;而Redis是遠(yuǎn)程緩存,存儲在內(nèi)存中,但可以通過網(wǎng)絡(luò)訪問。
- 性能:由于Caffeine是本地緩存,訪問速度更快,延遲更低;而Redis雖然性能也很高,但受限于網(wǎng)絡(luò)延遲。
- 持久化:Redis支持?jǐn)?shù)據(jù)持久化,即使服務(wù)器重啟也能恢復(fù)數(shù)據(jù);而Caffeine是內(nèi)存緩存,數(shù)據(jù)在服務(wù)器重啟后會丟失。
- 分布式:Redis是分布式緩存,支持多個節(jié)點之間的數(shù)據(jù)同步和共享;而Caffeine是本地緩存,無法跨進(jìn)程共享數(shù)據(jù)。
我們在哪些場景,選擇哪種緩存呢?
- 對于需要高性能和低延遲的應(yīng)用:如果數(shù)據(jù)量不大且不需要持久化,可以選擇Caffeine作為本地緩存。
- 對于需要跨進(jìn)程共享數(shù)據(jù)的應(yīng)用:如果數(shù)據(jù)量較大且需要持久化或跨進(jìn)程共享,可以選擇Redis作為遠(yuǎn)程緩存。
其實,實際開發(fā)中,我們都是結(jié)合兩者一起使用的。
它兩還可以實現(xiàn)多級緩存策略。例如,將熱點數(shù)據(jù)緩存到Caffeine中,以提高訪問速度;將非熱點數(shù)據(jù)緩存到Redis中,以實現(xiàn)跨進(jìn)程共享和持久化。 這個合理嘛?熱點數(shù)據(jù)不可以放redis?
6. 代碼實現(xiàn)
1)先引入maven包:
<!-- Spring Boot Starter Cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Caffeine Cache -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
2)實現(xiàn)CacheConfig緩存配置管理器
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("book");
cacheManager.setCaffeine(caffeineCacheBuilder());
return cacheManager;
}
Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.maximumSize(500) // 設(shè)置緩存的最大容量
.expireAfterWrite(10, TimeUnit.MINUTES); // 設(shè)置寫入后過期時間
}
}
3)在需要添加緩存的地方加個注解即可,很簡單
@Override
@Cacheable("book")
public BookVO queryBookById(Integer bookId) {
BookPO bookPO = bookRepository.queryBookById(bookId);
BookVO bookVO = new BookVO();
BeanUtils.copyProperties(bookPO, bookVO);
log.info("查詢書本:{}", bookId);
return bookVO;
}