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

