1. 引言
在构建高并发、高性能的 Spring Boot 应用时,缓存是提高访问速度、降低数据库负载的重要手段之一。Redis 作为一个高性能的键值对存储数据库,非常适合作为缓存层。本文将详细介绍如何在 Spring Boot 中整合 Redis 实现缓存管理。
2. Redis 简介与安装
Redis 简介
Redis 是一个开源的、使用内存存储数据的键值对数据库,它可以支持多种类型的数据结构,如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。由于其高性能和丰富的数据结构支持,Redis 常被用作缓存、消息队列等场景。
Redis 安装
- 下载 Redis:访问 Redis 官方网站(https://redis.io/download),下载最新版本的 Redis 源代码包或二进制包。
- 解压:将下载的包解压到指定目录。
- 编译(可选):如果下载的是源代码包,需要编译成可执行文件。通常二进制包已经编译好了,可以直接使用。
- 启动 Redis:进入 Redis 目录,运行
./redis-server
命令启动 Redis 服务。 - 测试连接:运行
./redis-cli
命令,输入一些 Redis 命令(如set key value
、get key
)测试连接。
(注:以下图片展示了 Redis 的下载、解压和启动过程)
3. Spring Boot 整合 Redis
要在 Spring Boot 中整合 Redis,首先需要添加 Redis 相关的依赖。
添加依赖
在 pom.xml
文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置 Redis
在 application.properties
或 application.yml
文件中配置 Redis 的连接信息:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword # 如果没有设置密码,可以省略此行
4. 配置 Redis 作为缓存管理器
Spring Boot 提供了 CacheManager
接口,Redis 可以作为该接口的一个实现。我们需要在配置类中配置 RedisCacheManager。
配置类
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 设置缓存过期时间
.serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); // 设置值序列化器
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
// 自定义 Key 生成器(可选)
@Bean("customKeyGenerator")
public KeyGenerator customKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append(".");
sb.append(method.getName());
sb.append("(");
for (Object obj : params) {
sb.append(obj.toString());
}
sb.append(")");
return sb.toString();
};
}
}
5. 使用 RedisTemplate 操作 Redis
虽然我们可以直接使用 Spring Cache 注解来操作缓存,但有时需要直接操作 Redis。这时可以使用 RedisTemplate
。
配置 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
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void setCache(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getCache(String key) {
return redisTemplate.opsForValue().get(key);
}
public void deleteCache(String key) {
redisTemplate.delete(key);
}
}
6. 自定义缓存注解
有时我们需要更灵活地控制缓存行为,可以自定义缓存注解。
自定义注解
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyCacheable {
String value();
String key() default "";
long ttl() default 3600; // 默认缓存过期时间(秒)
}
自定义缓存拦截器
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class MyCacheAspect {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private CacheManager cacheManager;
@Around("@annotation(myCacheable)")
public Object around(ProceedingJoinPoint joinPoint, MyCacheable myCacheable) throws Throwable {
String cacheName = myCacheable.value();
String key = myCacheable.key().isEmpty() ? new SimpleKeyGenerator().generate(joinPoint.getArgs(), joinPoint.getTarget().getClass()) : myCacheable.key();
Object value = redisTemplate.opsForValue().get(key);
if (value != null) {
return value;
}
Object result = joinPoint.proceed();
redisTemplate.opsForValue().set(key, result, myCacheable.ttl(), TimeUnit.SECONDS);
// 可选:将缓存同步到 CacheManager(如果使用了 Spring Cache)
// cacheManager.getCache(cacheName).put(key, result);
return result;
}
}
7. 遇到的问题与解决过程
问题 1:Redis 连接失败
- 现象:启动应用时,报错
Connection refused
。 - 原因:Redis 服务未启动或配置信息错误。
- 解决:确保 Redis 服务已启动,并检查
application.properties
中的 Redis 配置信息。
问题 2:- - - - - -