redis在springboot中做緩存操作的兩種方法應(yīng)用實(shí)例
眾所周知,redis是一個(gè)高性能的鍵值對(duì)存儲(chǔ)數(shù)據(jù)庫,在現(xiàn)在的程序構(gòu)建時(shí),當(dāng)數(shù)據(jù)量較大時(shí)或數(shù)據(jù)重復(fù)利用時(shí)常常利用緩存技術(shù)來減少時(shí)間消耗和資源浪費(fèi),本文就是介紹在springboot中如何利用redis做緩存
一.進(jìn)行redis的安裝與開啟(簡略)
在windows系統(tǒng)或Linux系統(tǒng)都可
默認(rèn)已安裝完redis
二.進(jìn)行依賴引入和配置文件搭建
依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
配置文件(application.properties)
spring.redis.host=(你redis主機(jī)的ip地址)
spring.redis.port=6379
spring.redis.password=
# 可選連接池配置
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
三.構(gòu)建config以及加注解
在主啟動(dòng)類添加@EnableCaching注解:
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}配置Redis緩存管理器
@Configuration
public class RedisCacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.entryTtl(Duration.ofMinutes(30)); // 默認(rèn)過期時(shí)間30分鐘
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.withCacheConfiguration("userCache", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))) // 自定義緩存過期
.transactionAware()
.build();
}
}userCache"這是緩存名稱。在 Spring 應(yīng)用程序中,你可以通過指定不同的緩存名稱來管理不同的緩存區(qū)域。
管理器中進(jìn)行了與redis的連接還有序列化(數(shù)據(jù)庫中存儲(chǔ)的形式)
例如,如果你緩存了一個(gè) User 對(duì)象,它會(huì)被序列化為 JSON 字符串,然后存儲(chǔ)在 Redis 中。在 Redis 中,數(shù)據(jù)看起來可能是這樣的:
"key": "{\"id\":\"1\",\"name\":\"John Doe\",\"email\":\"john.doe@example.com\"}"
四.接下來就是要進(jìn)行緩存管理
緩存操作管理通常有兩種方式分別為 聲明式注解緩存(Annotation-based Caching)和命令式編程(Imperative Caching with RedisTemplate),接下來就談?wù)勎覍?duì)這兩種方法的理解及其運(yùn)用
提示:通過我的RedisCacheConfig文件序列化后,我們?cè)趓edis數(shù)據(jù)庫中的對(duì)象就是字符串類型的方式來存儲(chǔ)
1.聲明式注解緩存(Annotation-based Caching)
核心思想
通過 AOP(面向切面編程)實(shí)現(xiàn),開發(fā)者通過注解聲明緩存行為,由框架自動(dòng)完成緩存的讀寫和失效管理。
應(yīng)用示例
(1) 讀取數(shù)據(jù)優(yōu)先緩存
@Cacheable(value = "userCache", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}原理:
方法執(zhí)行前檢查 userCache::id 是否存在(
value = "userCache"
標(biāo)識(shí)該緩存屬于名為userCache的緩存區(qū)(Cache Region),對(duì)應(yīng)Redis中的鍵前綴(如userCache::1)
key = "#id"
使用SpEL表達(dá)式定義緩存鍵,此處表示用方法參數(shù)id的值作為鍵的后綴
)
存在則直接返回緩存值
不存在則執(zhí)行方法體,將結(jié)果存入緩存
unless 確??罩挡痪彺妫ǚ乐咕彺娲┩福?/p>
(2) 更新數(shù)據(jù)后刷新緩存
@CachePut(value = "userCache", key = "#user.id")
public User updateUser(User user) {
return userRepository.save(user); // 強(qiáng)制更新緩存
}原理:
- 無論緩存是否存在,始終執(zhí)行方法體
- 將返回結(jié)果覆蓋舊緩存
(3) 刪除數(shù)據(jù)后清理緩存
@CacheEvict(value = "userCache", key = "#id", beforeInvocation = true)
public void deleteUser(Long id) {
userRepository.deleteById(id);
}原理:
beforeInvocation = true表示在方法執(zhí)行前刪除緩存(避免方法執(zhí)行失敗導(dǎo)致緩存殘留)
2.命令式編程緩存(Imperative Caching with RedisTemplate)
核心思想
通過 RedisTemplate 直接操作 Redis 的 API,開發(fā)者需手動(dòng)控制緩存邏輯,靈活性更高。
首先要配置一個(gè)RedisTemplate
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 設(shè)置 key 序列化器
template.setKeySerializer(new StringRedisSerializer());
// 設(shè)置 value 序列化器
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}RedisTemplate 是 Spring Data Redis 提供的一個(gè)用于操作 Redis 的模板類。它包含了很多操作 Redis 的方法,主要分為以下幾類:
通用操作
hasKey(K key): 檢查 key 是否存在。
delete(K key): 刪除 key。
delete(Collection<K> keys): 批量刪除 keys。
expire(K key, long timeout, TimeUnit unit): 設(shè)置 key 的過期時(shí)間。
expireAt(K key, Date date): 設(shè)置 key 在指定時(shí)間過期。
keys(K pattern): 查找所有符合給定模式 pattern 的 key。
move(K key, int dbIndex): 將 key 移動(dòng)到指定的數(shù)據(jù)庫。
randomKey(): 隨機(jī)返回一個(gè) key。
rename(K oldKey, K newKey): 重命名 key。
type(K key): 返回 key 的類型。
字符串操作
opsForValue(): 獲取字符串操作對(duì)象,進(jìn)而可以使用如 set, get, increment, decrement 等方法。
列表操作
opsForList(): 獲取列表操作對(duì)象,進(jìn)而可以使用如 leftPush, rightPush, range, size 等方法。
集合操作
opsForSet(): 獲取集合操作對(duì)象,進(jìn)而可以使用如 add, members, size, isMember 等方法。
有序集合操作
opsForZSet(): 獲取有序集合操作對(duì)象,進(jìn)而可以使用如 add, range, rangeByScore, score 等方法。
哈希操作
opsForHash(): 獲取哈希操作對(duì)象,進(jìn)而可以使用如 put, get, entries, keys, values 等方法。
事務(wù)操作
execute(RedisCallback<T> action): 執(zhí)行一個(gè) RedisCallback。
executePipelined(RedisCallback<T> action): 以管道的方式執(zhí)行多個(gè)命令。
multi(): 標(biāo)記事務(wù)開始。
exec(): 執(zhí)行所有事務(wù)塊內(nèi)的命令。
這些方法提供了對(duì) Redis 數(shù)據(jù)結(jié)構(gòu)的基本操作,可以滿足大部分的使用場景。需要注意的是,這些操作都是同步的,如果需要異步操作,可以使用 RedisTemplate 的異步版本 StringRedisTemplate。
應(yīng)用示例
(1) 手動(dòng)緩存讀取與寫入
public User getUserById(Long id) {
// 生成緩存鍵,格式為 "user:{id}"(如 "user:123")
String cacheKey = "user:" + id;
// 獲取 Redis 的 String 類型操作接口
ValueOperations<String, User> ops = redisTemplate.opsForValue();
// 嘗試從 Redis 中獲取緩存數(shù)據(jù)
User user = ops.get(cacheKey);
// 緩存未命中(包含空值標(biāo)記的情況)
if (user == null) {
// 穿透到數(shù)據(jù)庫查詢真實(shí)數(shù)據(jù)
user = userRepository.findById(id).orElse(null);
if (user != null) {
// 數(shù)據(jù)庫存在數(shù)據(jù):寫入緩存并設(shè)置 30 分鐘過期時(shí)間
ops.set(cacheKey, user, Duration.ofMinutes(30));
} else {
// 數(shù)據(jù)庫不存在數(shù)據(jù):寫入特殊空值標(biāo)記,設(shè)置 5 分鐘較短過期時(shí)間
// 使用 new NullValue() 而非 null 是為了區(qū)分:
// 1. 真實(shí)緩存空值(防止穿透)
// 2. Redis 未存儲(chǔ)該鍵(真正的緩存未命中)
ops.set(cacheKey, new NullValue(), Duration.ofMinutes(5));
}
}
// 返回前進(jìn)行空值標(biāo)記判斷
return user instanceof NullValue ? null : user;
}特點(diǎn):
完全手動(dòng)控制緩存邏輯
可精細(xì)處理空值緩存和 TTL
(2) 操作復(fù)雜數(shù)據(jù)結(jié)構(gòu)(Hash)
public void updateUserProfile(Long userId, Map<String, String> profile) {
String hashKey = "userProfiles";
redisTemplate.opsForHash().putAll(hashKey, profile);
// 設(shè)置整個(gè) Hash 的過期時(shí)間
redisTemplate.expire(hashKey, Duration.ofHours(24));
}3.兩種方式的深度對(duì)比
| 維度 | 聲明式注解緩存 (@Cacheable 等) | 命令式編程緩存 (RedisTemplate) |
|---|---|---|
| 抽象層級(jí) | 高層抽象,屏蔽緩存實(shí)現(xiàn)細(xì)節(jié) | 底層操作,直接面向 Redis API |
| 代碼侵入性 | 無侵入(通過注解實(shí)現(xiàn)) | 顯式代碼調(diào)用 |
| 靈活性 | 有限(受限于注解參數(shù)) | 極高(可自由操作所有 Redis 命令) |
| 數(shù)據(jù)結(jié)構(gòu)支持 | 僅支持簡單鍵值對(duì)(通過序列化) | 支持所有 Redis 數(shù)據(jù)結(jié)構(gòu)(Hash/List 等) |
| 事務(wù)支持 | 與 Spring 事務(wù)管理集成 | 需手動(dòng)使用 multi/exec 或 SessionCallback |
| 異常處理 | 統(tǒng)一通過 CacheErrorHandler | 需自行 try-catch |
| 緩存策略配置 | 集中式配置(通過 RedisCacheManager) | 分散在代碼各處 |
| 性能優(yōu)化 | 自動(dòng)批量化(部分實(shí)現(xiàn)支持) | 分散在代碼各處 |
最后 關(guān)鍵場景選擇建議
(1) 優(yōu)先使用注解的場景
簡單的 CRUD 緩存需求
需要快速實(shí)現(xiàn)緩存邏輯
希望代碼保持簡潔(如業(yè)務(wù)層方法只需關(guān)注核心邏輯)
需要兼容多緩存后端(如同時(shí)支持 Redis 和本地緩存)
(2) 必須使用命令式的場景
操作 Redis 特有數(shù)據(jù)結(jié)構(gòu)(如 GEO、HyperLogLog)
實(shí)現(xiàn)分布式鎖、限流等高級(jí)功能
需要精細(xì)控制每個(gè)操作的 TTL
使用事務(wù)、Pipeline 等 Redis 特性
到此這篇關(guān)于redis在springboot中做緩存操作的兩種方法的文章就介紹到這了,更多相關(guān)redis springboot緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Redis中的簡單動(dòng)態(tài)字符串和C字符串的區(qū)別
簡單動(dòng)態(tài)字符串(SDS)和?C?字符串在實(shí)現(xiàn)和特性上存在一些區(qū)別,這些區(qū)別使得?SDS?更適合作為?Redis?中字符串對(duì)象的內(nèi)部表示,本文給大家介紹一下Redis中的簡單動(dòng)態(tài)字符串和C字符串的區(qū)別,需要的朋友可以參考下2023-12-12
RedisDesktopManager無法遠(yuǎn)程連接Redis的完美解決方法
下載RedisDesktopManager客戶端,輸入服務(wù)器IP地址,端口(缺省值:6379);點(diǎn)擊Test Connection按鈕測試連接,連接失敗,怎么回事呢?下面小編給大家?guī)砹薘edisDesktopManager無法遠(yuǎn)程連接Redis的完美解決方法,一起看看吧2018-03-03
redis連接報(bào)錯(cuò)error:NOAUTH Authentication required
本文主要介紹了redis連接報(bào)錯(cuò)error:NOAUTH Authentication required,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
Redis結(jié)合Caffeine兩級(jí)緩存的三種實(shí)現(xiàn)方式
本文主要介紹了Redis結(jié)合Caffeine兩級(jí)緩存的實(shí)現(xiàn)示例,通過手動(dòng)、Spring注解及自定義切面三種方式實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-08-08
淺談Redis高并發(fā)緩存架構(gòu)性能優(yōu)化實(shí)戰(zhàn)
本文主要介紹了淺談Redis高并發(fā)緩存架構(gòu)性能優(yōu)化實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
Redis 主從搭建的實(shí)現(xiàn)(同主機(jī)和跨節(jié)點(diǎn))
本文主要介紹了Redis 主從搭建的實(shí)現(xiàn),包括同主機(jī)和跨節(jié)點(diǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-09-09
使用redis獲取自增序列號(hào)實(shí)現(xiàn)方式
這篇文章主要介紹了使用redis獲取自增序列號(hào)實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12

