redis在springboot中做缓存操作的两种方法应用实例

 更新时间:2025年09月24日 09:30:36   作者:梦兮760  
redis是一个高性能的键值对存储数据库,在现在的程序构建时,当数据量较大时或数据重复利用时常常利用缓存技术来减少时间消耗和资源浪费,本文就是介绍在springboot中如何利用redis做缓存,感兴趣的朋友跟随小编一起看看吧

众所周知,redis是一个高性能的键值对存储数据库,在现在的程序构建时,当数据量较大时或数据重复利用时常常利用缓存技术来减少时间消耗和资源浪费,本文就是介绍在springboot中如何利用redis做缓存

一.进行redis的安装与开启(简略)

在windows系统或Linux系统都可

默认已安装完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 应用程序中,你可以通过指定不同的缓存名称来管理不同的缓存区域。

管理器中进行了与redis的连接还有序列化(数据库中存储的形式)

例如,如果你缓存了一个 User 对象,它会被序列化为 JSON 字符串,然后存储在 Redis 中。在 Redis 中,数据看起来可能是这样的:

"key": "{\"id\":\"1\",\"name\":\"John Doe\",\"email\":\"john.doe@example.com\"}"

四.接下来就是要进行缓存管理

缓存操作管理通常有两种方式分别为 声明式注解缓存(Annotation-based Caching)命令式编程(Imperative Caching with RedisTemplate),接下来就谈谈我对这两种方法的理解及其运用

提示:通过我的RedisCacheConfig文件序列化后,我们在redis数据库中的对象就是字符串类型的方式来存储

1.声明式注解缓存(Annotation-based Caching)

核心思想
通过 AOP(面向切面编程)实现,开发者通过注解声明缓存行为,由框架自动完成缓存的读写和失效管理。

应用示例

(1) 读取数据优先缓存

@Cacheable(value = "userCache", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}

原理:

方法执行前检查 userCache::id 是否存在(

value = "userCache"
标识该缓存属于名为userCache的缓存区(Cache Region),对应Redis中的键前缀(如userCache::1)

key = "#id"
使用SpEL表达式定义缓存键,此处表示用方法参数id的值作为键的后缀

存在则直接返回缓存值

不存在则执行方法体,将结果存入缓存

unless 确保空值不缓存(防止缓存穿透)

(2) 更新数据后刷新缓存

@CachePut(value = "userCache", key = "#user.id")
public User updateUser(User user) {
    return userRepository.save(user); // 强制更新缓存
}

原理

  • 无论缓存是否存在,始终执行方法体
  • 将返回结果覆盖旧缓存

(3) 删除数据后清理缓存

@CacheEvict(value = "userCache", key = "#id", beforeInvocation = true)
public void deleteUser(Long id) {
    userRepository.deleteById(id);
}

原理

  • beforeInvocation = true 表示在方法执行前删除缓存(避免方法执行失败导致缓存残留)

2.命令式编程缓存(Imperative Caching with RedisTemplate)

核心思想

通过 RedisTemplate 直接操作 Redis 的 API,开发者需手动控制缓存逻辑,灵活性更高。

首先要配置一个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 移动到指定的数据库。
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): 执行一个 RedisCallback。
executePipelined(RedisCallback<T> action): 以管道的方式执行多个命令。
multi(): 标记事务开始。
exec(): 执行所有事务块内的命令。
这些方法提供了对 Redis 数据结构的基本操作,可以满足大部分的使用场景。需要注意的是,这些操作都是同步的,如果需要异步操作,可以使用 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 中获取缓存数据
    User user = ops.get(cacheKey);
    // 缓存未命中(包含空值标记的情况)
    if (user == null) {
        // 穿透到数据库查询真实数据
        user = userRepository.findById(id).orElse(null);
        if (user != null) {
            // 数据库存在数据:写入缓存并设置 30 分钟过期时间
            ops.set(cacheKey, user, Duration.ofMinutes(30)); 
        } else {
            // 数据库不存在数据:写入特殊空值标记,设置 5 分钟较短过期时间
            // 使用 new NullValue() 而非 null 是为了区分:
            // 1. 真实缓存空值(防止穿透)
            // 2. Redis 未存储该键(真正的缓存未命中)
            ops.set(cacheKey, new NullValue(), Duration.ofMinutes(5));
        }
    }
    // 返回前进行空值标记判断
    return user instanceof NullValue ? null : user;
}

特点:

完全手动控制缓存逻辑

可精细处理空值缓存和 TTL

(2) 操作复杂数据结构(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)
抽象层级高层抽象,屏蔽缓存实现细节底层操作,直接面向 Redis API
代码侵入性无侵入(通过注解实现)显式代码调用
灵活性有限(受限于注解参数)极高(可自由操作所有 Redis 命令)
数据结构支持仅支持简单键值对(通过序列化)支持所有 Redis 数据结构(Hash/List 等)
事务支持与 Spring 事务管理集成需手动使用 multi/exec 或 SessionCallback
异常处理统一通过 CacheErrorHandler需自行 try-catch
缓存策略配置集中式配置(通过 RedisCacheManager分散在代码各处
性能优化自动批量化(部分实现支持)分散在代码各处

最后 关键场景选择建议

(1) 优先使用注解的场景
简单的 CRUD 缓存需求

需要快速实现缓存逻辑

希望代码保持简洁(如业务层方法只需关注核心逻辑)

需要兼容多缓存后端(如同时支持 Redis 和本地缓存)

(2) 必须使用命令式的场景
操作 Redis 特有数据结构(如 GEO、HyperLogLog)

实现分布式锁、限流等高级功能

需要精细控制每个操作的 TTL

使用事务、Pipeline 等 Redis 特性

到此这篇关于redis在springboot中做缓存操作的两种方法的文章就介绍到这了,更多相关redis springboot缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Redis中的简单动态字符串和C字符串的区别

    详解Redis中的简单动态字符串和C字符串的区别

    简单动态字符串(SDS)和 C 字符串在实现和特性上存在一些区别,这些区别使得 SDS 更适合作为 Redis 中字符串对象的内部表示,本文给大家介绍一下Redis中的简单动态字符串和C字符串的区别,需要的朋友可以参考下
    2023-12-12
  • RedisDesktopManager无法远程连接Redis的完美解决方法

    RedisDesktopManager无法远程连接Redis的完美解决方法

    下载RedisDesktopManager客户端,输入服务器IP地址,端口(缺省值:6379);点击Test Connection按钮测试连接,连接失败,怎么回事呢?下面小编给大家带来了RedisDesktopManager无法远程连接Redis的完美解决方法,一起看看吧
    2018-03-03
  • redis分布式ID解决方案示例详解

    redis分布式ID解决方案示例详解

    这篇文章主要为大家介绍了redis分布式ID解决方案示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • redis连接报错error:NOAUTH Authentication required

    redis连接报错error:NOAUTH Authentication required

    本文主要介绍了redis连接报错error:NOAUTH Authentication required,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Redis结合Caffeine两级缓存的三种实现方式

    Redis结合Caffeine两级缓存的三种实现方式

    本文主要介绍了Redis结合Caffeine两级缓存的实现示例,通过手动、Spring注解及自定义切面三种方式实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-08-08
  • 浅谈Redis高并发缓存架构性能优化实战

    浅谈Redis高并发缓存架构性能优化实战

    本文主要介绍了浅谈Redis高并发缓存架构性能优化实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • React中immutable的使用

    React中immutable的使用

    这篇文章主要介绍了React中immutable的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Redis中LFU算法的深入分析

    Redis中LFU算法的深入分析

    这篇文章主要给大家介绍了关于Redis中LFU算法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • Redis 主从搭建的实现(同主机和跨节点)

    Redis 主从搭建的实现(同主机和跨节点)

    本文主要介绍了Redis 主从搭建的实现,包括同主机和跨节点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • 使用redis获取自增序列号实现方式

    使用redis获取自增序列号实现方式

    这篇文章主要介绍了使用redis获取自增序列号实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论