SpringBoot + Redis 配置详解
本文将详细介绍SpringBoot与Redis的整合配置,包括依赖引入、连接配置、序列化设置、缓存注解使用等内容,帮助开发者快速实现Redis缓存功能。
一、依赖配置
首先在pom.xml
中添加必要的依赖:
xml
<!-- Redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池依赖(Spring Boot 2.x 默认使用 Lettuce 客户端) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 可选:如果使用 Jedis 客户端替代 Lettuce -->
<!-- <dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency> -->
二、基本连接配置 (application.yml)
在application.yml
中配置Redis连接信息:
yaml
spring:
redis:
# Redis 服务器地址
host: localhost
# Redis 端口
port: 6379
# Redis 密码(若未设置密码,可省略此配置)
password: 123456
# 数据库索引(Redis支持0-15共16个数据库)
database: 0
# 连接超时时间(毫秒)
timeout: 3000ms
# Lettuce连接池配置(Spring Boot 2.x 默认)
lettuce:
pool:
# 最大活跃连接数
max-active: 8
# 最大空闲连接数
max-idle: 8
# 最小空闲连接数
min-idle: 2
# 连接池最大阻塞等待时间
max-wait: 1000ms
# 或使用Jedis连接池配置(需要引入Jedis依赖)
# jedis:
# pool:
# max-active: 15
# max-idle: 10
# min-idle: 5
# max-wait: 5000ms
# 缓存配置
cache:
# 缓存类型:指定为Redis
type: redis
# Redis缓存配置
redis:
# 缓存过期时间
time-to-live: 3600000ms
# 是否允许缓存空值(防止缓存穿透)
cache-null-values: true
# 缓存键前缀
key-prefix: "spring-boot-redis:"
# 是否使用键前缀
use-key-prefix: true
三、RedisTemplate 配置类
创建自定义配置类,配置RedisTemplate序列化方式和各种Operations:
java
@Configuration
@EnableCaching
public class RedisConfig {
/**
* 配置自定义的RedisTemplate
* 设置Key和Value的序列化方式
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(factory);
// 设置Key序列化器
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
// 设置Value序列化器(可选择不同的序列化方式)
// 1. JDK序列化(默认,但可读性差)
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.setHashValueSerializer(RedisSerializer.java());
// 2. JSON序列化(推荐,可读性好)
/*
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
*/
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 配置StringRedisTemplate(专用字符串操作)
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(factory);
return stringRedisTemplate;
}
/**
* 配置HashOperations
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 配置ValueOperations
*/
@Bean
public ValueOperations<String, String> valueOperations(StringRedisTemplate stringRedisTemplate) {
return stringRedisTemplate.opsForValue();
}
/**
* 配置ListOperations
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 配置SetOperations
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 配置ZSetOperations
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
/**
* 配置缓存管理器
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 设置缓存有效期
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.java()))
.disableCachingNullValues(); // 不缓存空值
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
四、使用RedisTemplate操作Redis
1. 注入RedisTemplate
java
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 或使用StringRedisTemplate(更适合纯字符串操作)
@Autowired
private StringRedisTemplate stringRedisTemplate;
}
2. 基本操作示例
java
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
// String操作
public void setString(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
public String getString(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
// 对象操作
public void setObject(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getObject(String key) {
return redisTemplate.opsForValue().get(key);
}
// 带过期时间的设置
public void setStringWithExpire(String key, String value, long timeout, TimeUnit unit) {
stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
}
// 删除操作
public void delete(String key) {
redisTemplate.delete(key);
}
// 判断key是否存在
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
// Hash操作
public void putHash(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
public Object getHash(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
// List操作
public void leftPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
public Object leftPop(String key) {
return redisTemplate.opsForList().leftPop(key);
}
}
五、使用缓存注解
1. 启用缓存
在主应用类或配置类上添加@EnableCaching
注解:
java
@SpringBootApplication
@EnableCaching
public class SpringBootRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRedisApplication.class, args);
}
}
2. 常用缓存注解使用
java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
/**
* 将查询结果缓存
*/
@Cacheable(value = "user", key = "#id")
public User getUserById(Long id) {
System.out.println("从数据库查询用户信息,id: " + id);
return userRepository.findById(id).orElse(null);
}
/**
* 更新缓存
*/
@CachePut(value = "user", key = "#user.id")
public User updateUser(User user) {
System.out.println("更新用户信息,id: " + user.getId());
return userRepository.save(user);
}
/**
* 删除缓存
*/
@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) {
System.out.println("删除用户信息,id: " + id);
userRepository.deleteById(id);
}
/**
* 清除所有缓存
*/
@CacheEvict(value = "user", allEntries = true)
public void clearCache() {
System.out.println("清除所有用户缓存");
}
}
六、序列化方式选择
Spring Data Redis提供多种序列化方式:
-
JdkSerializationRedisSerializer:
- 默认序列化方式
- 优点:支持任何可序列化对象
- 缺点:序列化后数据体积大,可读性差
-
Jackson2JsonRedisSerializer:
- JSON序列化,可读性好
- 优点:序列化后数据体积小,可读性高
- 缺点:需要配置类型信息以支持反序列化到具体类型
-
StringRedisSerializer:
- 字符串序列化,主要用于键
- 优点:高效,可读性好
- 缺点:只能序列化字符串
-
GenericJackson2JsonRedisSerializer:
- 通用JSON序列化
- 优点:自动包含类型信息,使用方便
- 缺点:序列化结果会包含类型信息,数据量稍大
七、Redis连接池配置说明
Lettuce vs Jedis
Spring Boot 2.x默认使用Lettuce作为Redis客户端,相比Jedis:
-
Lettuce:
- 基于Netty的异步客户端
- 线程安全
- 支持异步操作
- 默认选择
-
Jedis:
- 同步阻塞客户端
- 非线程安全,需要使用连接池
- 操作简单直观
连接池参数调优建议
- max-active:根据并发量设置,推荐为CPU核心数的10倍左右
- max-idle:保持的最大空闲连接数,建议与max-active一致
- min-idle:保持的最小空闲连接数,建议设置为5-10
- max-wait:获取连接的最大等待时间,建议设置为1000-5000ms
- timeout:连接超时时间,建议设置为3000-5000ms
八、常见问题与解决方案
-
缓存穿透问题:
- 解决方案:缓存空值(
cache-null-values: true
)或使用布隆过滤器
- 解决方案:缓存空值(
-
缓存击穿问题:
- 解决方案:热点数据设置永不过期或使用互斥锁
-
缓存雪崩问题:
- 解决方案:设置随机过期时间或使用多级缓存
-
序列化问题:
- 解决方案:确保对象实现Serializable接口,或使用JSON序列化
-
连接池耗尽:
- 解决方案:增加连接池大小,检查是否有连接未正确释放
通过以上配置和最佳实践,可以有效实现SpringBoot与Redis的整合,充分利用Redis的高性能缓存能力,提升应用性能。