SpringBoot Redis 實踐指南
- 2022 年 5 月 17 日
- 筆記
- Redis, springboot, 妹子、程式碼與貓
前言
SpringBoot Cache 是一個很好的快取框架,可以兼容多種快取實現,數據量較大的情況下,Redis 應該是最多被使用的。
本文重點介紹 SpringBoot 和 Redis 整合使用的關鍵流程,並對其中的核心要點給出說明,且附上相應的官方文檔鏈接便於參考。
添加 Maven 依賴
在項目 pom.xml 中添加如下配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
啟用快取
在項目 啟動類 中添加如下注解:
@EnableCaching
配置快取
配置 Redis 連接資訊
Redis 連接資訊包括地址、埠、超時時間(秒)和連接池等,可以根據需要選取若干配置即可。
在項目 application.yml 中添加如下配置:
spring:
redis:
host: ${host}
port: ${port}
timeout: 3000
lettuce:
pool:
enabled: true
max-active: 30
SpringBoot 默認使用的 Redis 客戶端是 lettuce,不是 Jedis。如果需要使用連接池的話,還需要額外添加一個 Maven 依賴:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${commons-pool2.version}</version>
</dependency>
Redis 連接配置屬性參考,注意屬性前綴為 spring.redis.*。
配置快取資訊
SpringBoot 支援多個不同名稱的快取,快取名稱需要預先配置,還可以指定快取的過期時間。對於 Redis 而言,某個名稱的快取實際上就是 Redis 中一個或多個以該名稱為前綴的 Key,快取的過期時間指的就是這部分 Key 的過期時間。
在項目 application.yml 中添加如下配置:
spring:
cache:
cache-names: "cache1,cache2"
redis:
time-to-live: "10m"
快取配置屬性參考,注意屬性前綴為 spring.cache.redis.*。
默認情況下,所有快取的過期時間都是一樣的。如果需要對不同的快取設置不同的過期時間,可以自己擴展實現,參考官方示例。
使用快取
@Cacheable
SpringBoot Cache 可以幫助我們自動快取某個方法的結果(返回值),使用時我們只需要在方法上面添加註解 @Cacheable,並且指定快取名稱即可:
@Cacheable(cacheNames = {"cos::url"})
public String generatePresignedUrl(String name) {
return ...;
}
快取名稱為 cos::url,調用方法 generatePresignedUrl 時,SpringBoot Cache 會自動檢查 Redis 中是否已經快取過該方法的結果,如果已經快取過,則直接使用快取中的結果返回,該方法不會執行;如果沒有快取過,會執行該方法獲取結果,快取結果之後再返回給調用者。
Key Generation
Redis 檢查或快取結果時均需要一個 Key,SpringBoot Cache 使用 快取名稱(CacheName,如:cos::url)和 參數值(ParameterValue,如:value1)生成 Key,規則如下:
- 如果方法沒有參數,Key 為 CacheName::SimpleKey [],即:cos::url::SimpleKey [];
- 如果方法只有一個參數,Key 為 CacheName::ParameterValue,即:cos::url::value1;
- 如果方法有兩個或兩個以上的參數,Key 為 CacheName::SimpleKey [ParameterValue1,ParameterValue2,…],即:cos::url::SimpleKey [value1,value2];
sync
sync 是註解 @Cacheable 的一個屬性,值可以是 true 或 false:
如果 sync = false(默認),多執行緒環境下調用方法 generatePresignedUrl 時,Redis 沒有快取結果的情況下,方法可能會被執行多次;
如果 sync = true,Redis 沒有快取結果的情況下,方法 generatePresignedUrl 只會被執行一次。
condition
condition 是註解 @Cacheable 的一個屬性,它的值是一個 SpEL 表達式,表達式的計算結果可以是 true 或 false:
如果表達式的計算結果是 true,表示快取方法結果;
如果表達式的計算結果是 false,表示不快取方法結果;
SpEL 表達式可以使用方法的參數值,也可以調用該方法所在 Bean 的其它方法,如:
#name.length() < 32
方法參數 name 的參數值長度小於 32 時,方法結果才會被快取;
condition = "#root.target.check(#name)"
check() 必須是公開的(public),且返回值必須是布爾類型(Boolean);只有 check() 返回值為 true 時,方法結果才會被快取。
使用限制
如果方法 generatePresignedUrl 被位於一個 Bean 的其它方法調用時,快取不會生效;也就是說,方法 generatePresignedUrl 必須被其它 Bean 的方法調用時,快取才會生效。原因主要是和 Spring 的代理機制有關,詳情可以參考:Spring Cache @Cacheable – not working while calling from another method of the same bean。
SpringBoot Cache 還支援其它註解,可以參考 Declarative Annotation-based Caching。
RedisTemplate
如果我們需要自己實現快取邏輯,SpringBoot Cache 提供了一個封裝 Redis 常用操作的工具模板類:RedisTemplate,並且會創建好它的實例,使用時直接注入即可:
@Autowired
private StringRedisTemplate template;
@Autowired
private RedisTemplate<String, String> template2;
@Autowired
private RedisTemplate<String, Integer> template3;
RedisTemplate 支援泛型,我們可以根據自己的需求注入一個或多個實例;如果鍵值的類型都是 String,可以直接使用 StringRedisTemplate。
結語
SpringBoot 整合 Redis 使用時,如果僅僅是需要讀取或快取數據,直接使用註解的方式相較於使用 RedisTemplate 的方式,可以避免大量的快取冗餘程式碼,更多地關注業務邏輯;但是缺點也比較明顯,操控性比較差。實際使用時,可以靈活結合兩者,優先使用註解方式;註解方式受限時,再結合 RedisTemplate 作為補充。