23《Spring Boot 入門教程》Spring Boot 緩存應(yīng)用場景

1. 前言

緩存是性能提升的大殺器!

要知道讳窟,內(nèi)存的讀寫速度是硬盤的幾十倍到上百倍让歼。緩存實際上就是利用內(nèi)存的高速讀寫特性,提高熱點數(shù)據(jù)的操作速度丽啡。

Spring Boot 中使用緩存非常簡單谋右,并且支持多種緩存實現(xiàn)。

本篇介紹比較常用的幾種緩存實現(xiàn)方式补箍,及其對應(yīng)的應(yīng)用場景改执。

2. Spring Boot 默認緩存

Spring Boot 默認緩存是基于 ConcurrenMapCacheManager 緩存管理器實現(xiàn)的啸蜜,從這個類名就能發(fā)現(xiàn)它本質(zhì)上應(yīng)該是一個 Map 集合容器。

ConcurrenMapCacheManager 結(jié)構(gòu)比較簡單辈挂,一般用于比較輕量級的緩存使用場景衬横。也就是緩存的數(shù)據(jù)量比較小,緩存操作不是特別頻繁的場景终蒂。

接下來就具體演示下蜂林, Spring Boot 默認緩存實現(xiàn)過程。

2.1 使用 Spring Initializr 創(chuàng)建項目

Spring Boot 版本選擇 2.2.5 拇泣,Group 為 com.imooc 噪叙, Artifact 為 spring-boot-cache ,生成項目后導(dǎo)入 Eclipse 開發(fā)環(huán)境霉翔。

2.2 引入項目依賴

引入 Web 項目依賴和緩存依賴睁蕾。

實例:

        <!-- Web 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 緩存依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

2.3 開啟緩存

在啟動類上添加注解 @EnableCaching 開啟緩存功能。

實例:

@SpringBootApplication
@EnableCaching // 開啟緩存
public class SpringBootCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootCacheApplication.class, args);
    }
}

2.4 定義服務(wù)層方法

正常服務(wù)層方法會調(diào)用數(shù)據(jù)訪問層方法訪問數(shù)據(jù)庫债朵,此處我們只需要演示緩存的作用子眶,所以打印日志代替數(shù)據(jù)庫訪問方法。

實例:

/**
 * 商品服務(wù)類
 */
@Service
@CacheConfig(cacheNames = "GoodsCache")
public class GoodsService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 按id獲取商品信息
     */
    @Cacheable
    public GoodsDo getById(Long id) {
        logger.info("getById({})", id);
        GoodsDo goods = new GoodsDo();
        goods.setId(id);
        goods.setName("goods-" + id);
        return goods;
    }

    /**
     * 刪除商品
     */
    @CacheEvict(key = "#id")
    public void remove(Long id) {
        logger.info("remove({})", id);
    }

    /**
     * 編輯商品信息
     */
    @CachePut(key = "#goods.id")
    public GoodsDo edit(GoodsDo goods) {
        logger.info("edit id:{}", goods.getId());
        return goods;
    }
}

對于使用緩存的 GoodsService 服務(wù)類序芦,我們需要具體解釋下:

  1. @CacheConfig 注解用于指定本類中方法使用的緩存名稱臭杰,該類使用的緩存名稱為 GoodsCache ,與其他緩存區(qū)域是隔離的芝加。
  2. @Cacheable 用于開啟方法緩存硅卢,緩存的鍵是方法的參數(shù)射窒,緩存的值是方法的返回值藏杖。如果多次調(diào)用該方法時參數(shù) id 值相同,則第一次會執(zhí)行方法體脉顿,并將返回值放入緩存蝌麸;后續(xù)方法不會再執(zhí)行方法體,直接將緩存的值返回艾疟。
  3. @CachePut 可以更新緩存来吩,key = "#id" 表示采用參數(shù)中的 id 屬性作為鍵。當(dāng)緩存中該鍵的值不存在時蔽莱,則將返回值放入緩存弟疆;當(dāng)緩存中該鍵的值已存在時,會更新緩存的內(nèi)容盗冷。
  4. @CacheEvict 可以移除緩存怠苔,當(dāng)調(diào)用該方法時,會移除 goods 中 id 屬性對應(yīng)的緩存內(nèi)容仪糖。

2.5 測試

為了充分理解緩存的含義柑司,我們通過測試類發(fā)起測試迫肖。

實例:

@SpringBootTest
class SpringBootCacheApplicationTests {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private GoodsService goodsService;

    // 顯示當(dāng)前使用的緩存管理器類型
    @Test
    void showCacheManager() {
        // 輸出:org.springframework.cache.concurrent.ConcurrentMapCacheManager
        logger.info(cacheManager.getClass().toString());
    }

    // 緩存測試
    @Test
    void cacheTest() {
        // 第一次執(zhí)行,沒有緩存攒驰,執(zhí)行方法體
        goodsService.getById(1L);
        // 再次執(zhí)行蟆湖,直接取出緩存,不執(zhí)行方法體
        goodsService.getById(1L);
        // 移除緩存
        goodsService.remove(1L);
        // 再次執(zhí)行玻粪,已經(jīng)沒有對應(yīng)緩存隅津,所以執(zhí)行方法體
        GoodsDo oldGoods = goodsService.getById(1L);
        // 打印緩存內(nèi)容
        logger.info("old goods id:{} name:{}", oldGoods.getId(), oldGoods.getName());
        // 更新緩存
        GoodsDo temp = new GoodsDo();
        temp.setId(1L);
        temp.setName("新的商品");
        goodsService.edit(temp);
        // 查詢并打印已更新的緩存內(nèi)容
        GoodsDo newGoods = goodsService.getById(1L);
        logger.info("new goods id:{} name:{}", newGoods.getId(), newGoods.getName());
    }

我們查看下控制臺輸出如下,驗證了我們設(shè)計的緩存機制劲室。

5ecd2b0e093b6d0610040135.jpg

使用 Spring Boot 默認緩存時控制臺輸出內(nèi)容

3. 使用 Ehcache 緩存

Spring Boot 默認的緩存實現(xiàn)比較簡單饥瓷,功能也十分有限。如果是企業(yè)級的中大型應(yīng)用痹籍,需要尋求更加穩(wěn)定呢铆、可靠的緩存框架。

Ehcache 是 Java 編程領(lǐng)域非常著名的緩存框架蹲缠,具備兩級緩存數(shù)據(jù)——內(nèi)存和磁盤棺克,因此不必擔(dān)心內(nèi)存容量問題。另外 Ehcache 緩存的數(shù)據(jù)會在 JVM 重啟時自動加載线定,不必擔(dān)心斷電丟失緩存的問題娜谊。

總之 Ehcache 的功能完整性和運行穩(wěn)定性遠遠強于 Spring Boot 默認的緩存實現(xiàn)方式,而且 Spring Boot 使用 Ehcache 非常便捷斤讥,接下來我們就來實現(xiàn)下纱皆。

3.1 添加 Ehcache 依賴

我們在 spring-boot-cache 項目的基礎(chǔ)上添加 Ehcache 依賴。

實例:

        <!-- Ehcache 依賴 -->
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <!-- cache-api 依賴 -->
        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
        </dependency>

3.2 添加 Ehcache 配置文件

首先在 application.properties 中指定配置文件的位置芭商。

實例:

spring.cache.jcache.config=classpath:ehcache.xml
spring.cache.type=jcache

然后在 resource 文件夾中添加 ehcache.xml 配置文件派草,內(nèi)容如下:

實例:

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns='http://www.ehcache.org/v3'
    xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd">
    <!-- 持久化路徑 -->
    <persistence directory="C://ehcache" />
    <!--緩存模板 -->
    <cache-template name="CacheTemplate">
        <expiry>
            <!--存活時間 -->
            <tti>60</tti>
        </expiry>
        <resources>
            <!--堆空間 -->
            <heap unit="entries">2000</heap>
            <!-- 堆外空間 -->
            <offheap unit="MB">500</offheap>
        </resources>
    </cache-template>

    <!--緩存對象 -->
    <cache alias="GoodsCache" uses-template="CacheTemplate">
    </cache>
</config>

Tips:Ehcache 的配置比較復(fù)雜,此處只是給出簡單的示例铛楣,感興趣的同學(xué)可以查閱更多資料近迁。

3.3 測試

由于之前已經(jīng)在啟動類添加 @EnableCaching ,我們再次運行測試類簸州,輸出結(jié)果如下鉴竭。

5ecd350c092863bb09090150.jpg

使用 Ehcache 時控制臺輸出內(nèi)容

注意控制臺出現(xiàn)了 EhcacheManager 的字樣,說明我們此時使用的緩存是 Ehcache 岸浑。

4. 使用 Redis 緩存

Ehcache 依然是 Java 進程內(nèi)的緩存框架搏存,受限于 JVM 整體的內(nèi)存分配策略。

如果是大型系統(tǒng)矢洲,緩存的數(shù)據(jù)量特別大璧眠,且性能要求很高,可以考慮直接使用 Redis 作為緩存。

Redis 可以采用單機蛆橡、主備舌界、集群等模式,視乎具體項目需求決定即可泰演。目前各大云計算廠商均提供商用版的 Redis 緩存服務(wù)呻拌,性能卓越且接入簡單快速。

本節(jié)簡單地演示 Spring Boot 中使用 Redis 單機緩存的方法睦焕,真實生產(chǎn)環(huán)境中建議至少使用主備類型的 Redis 實例藐握。

5ecd371a097c2a4507130257.jpg

華為云提供的緩存服務(wù)

4.1 修改緩存依賴

因為需要使用 Redis 緩存,所以將引入的依賴項修改如下:

實例:

        <!-- Web 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 緩存依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- Redis 相關(guān)依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

4.2 修改緩存配置

修改 application.properties 配置文件垃喊,將 Redis 配置及緩存配置設(shè)置如下:

實例:

# 過期時間
spring.cache.redis.time-to-live=6000s

# Redis庫的編號
spring.redis.database=0
# Redis實例地址
spring.redis.host=127.0.0.1
# Redis實例端口號猾普,默認6379
spring.redis.port=6379
# Redis登錄密碼
spring.redis.password=Easy@0122
# Redis連接池最大連接數(shù)
spring.redis.jedis.pool.max-active=10
# Redis連接池最大空閑連接數(shù)
spring.redis.jedis.pool.max-idle=10
# Redis連接池最小空閑連接數(shù)
spring.redis.jedis.pool.min-idle=0

4.3 測試

由于之前已經(jīng)通過注解 @EnableCaching 開啟了緩存功能,此時我們直接運行測試類進行測試本谜,輸出結(jié)果如下:

5ecdb411094c564d08370126.jpg

使用 Redis 緩存時控制臺輸出內(nèi)容

從上圖輸出結(jié)果可以看出初家,已經(jīng)成功使用了 Redis 緩存管理器。

另外我們可以直接使用 Redis 客戶端查看生成的緩存信息乌助,如下圖已經(jīng)有名為 GoodsCache::1 的緩存鍵存在了溜在。

5ecdb50609106a8409580133.jpg

Redis 客戶端查看緩存信息

5. 小結(jié)

Spring Boot 支持多種緩存實現(xiàn)方式,可以根據(jù)項目需求靈活選擇他托。

  • 緩存數(shù)據(jù)量較小的項目掖肋,可以使用 Spring Boot 默認緩存。
  • 緩存數(shù)據(jù)量較大的項目赏参,可以考慮使用 Ehcache 緩存框架志笼。
  • 如果是大型系統(tǒng),對緩存的依賴性比較高把篓,還是建議采用獨立的緩存組件 Redis 纫溃,通過主備、集群等形式提高緩存服務(wù)的性能和穩(wěn)定性纸俭。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皇耗,一起剝皮案震驚了整個濱河市南窗,隨后出現(xiàn)的幾起案子揍很,更是在濱河造成了極大的恐慌,老刑警劉巖万伤,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窒悔,死亡現(xiàn)場離奇詭異,居然都是意外死亡敌买,警方通過查閱死者的電腦和手機简珠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聋庵,你說我怎么就攤上這事膘融。” “怎么了祭玉?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵氧映,是天一觀的道長。 經(jīng)常有香客問我脱货,道長岛都,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任振峻,我火速辦了婚禮臼疫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扣孟。我一直安慰自己烫堤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布凤价。 她就那樣靜靜地躺著塔逃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪料仗。 梳的紋絲不亂的頭發(fā)上湾盗,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天,我揣著相機與錄音立轧,去河邊找鬼格粪。 笑死,一個胖子當(dāng)著我的面吹牛氛改,可吹牛的內(nèi)容都是我干的帐萎。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼胜卤,長吁一口氣:“原來是場噩夢啊……” “哼疆导!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起葛躏,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤澈段,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后舰攒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體败富,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年摩窃,在試婚紗的時候發(fā)現(xiàn)自己被綠了兽叮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鹦聪,靈堂內(nèi)的尸體忽然破棺而出账阻,到底是詐尸還是另有隱情,我是刑警寧澤泽本,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布宰僧,位于F島的核電站,受9級特大地震影響观挎,放射性物質(zhì)發(fā)生泄漏琴儿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一嘁捷、第九天 我趴在偏房一處隱蔽的房頂上張望造成。 院中可真熱鬧,春花似錦雄嚣、人聲如沸晒屎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鼓鲁。三九已至,卻和暖如春港谊,著一層夾襖步出監(jiān)牢的瞬間骇吭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工歧寺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留燥狰,地道東北人。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓斜筐,卻偏偏與公主長得像龙致,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子顷链,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內(nèi)容