在Spring Boot项目中使用Redis作为缓存或数据存储是非常常见的场景。以下是详细的实现步骤和示例代码:
一、添加依赖
在pom.xml
中添加Spring Data Redis依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池依赖(可选但推荐) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
二、配置Redis连接信息
在application.yml
或application.properties
中配置Redis服务器信息:
spring:
redis:
host: localhost # Redis服务器地址
port: 6379 # Redis服务器端口
password: # Redis密码(如果有)
database: 0 # 使用的数据库索引(0-15)
timeout: 3000ms # 连接超时时间
lettuce: # 使用Lettuce连接池(默认)
pool:
max-active: 8 # 最大连接数
max-wait: -1ms # 最大等待时间
max-idle: 8 # 最大空闲连接数
min-idle: 0 # 最小空闲连接数
三、配置RedisTemplate(可选)
默认情况下,Spring Boot会自动配置StringRedisTemplate
(键值为String类型)。如果需要自定义序列化方式或操作对象类型,可配置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 connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// 设置键的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// 设置值的序列化方式(使用JSON序列化)
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置哈希键的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// 设置哈希值的序列化方式
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
四、使用RedisTemplate操作Redis
以下是常见的Redis操作示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 存储键值对
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
// 存储键值对并设置过期时间
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
// 获取值
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// 删除键
public Boolean delete(String key) {
return redisTemplate.delete(key);
}
// 判断键是否存在
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
// 设置过期时间
public Boolean expire(String key, long timeout, TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
// 操作哈希表
public void hset(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
public Object hget(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
// 操作列表
public Long lpush(String key, Object value) {
return redisTemplate.opsForList().leftPush(key, value);
}
public Object rpop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
// 操作集合
public Long sadd(String key, Object... values) {
return redisTemplate.opsForSet().add(key, values);
}
// 操作有序集合
public Boolean zadd(String key, Object value, double score) {
return redisTemplate.opsForZSet().add(key, value, score);
}
}
五、使用@Cacheable注解实现缓存
Spring提供了@Cacheable
、@CacheEvict
等注解简化缓存操作:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
// @Cacheable:先从缓存中查找,不存在则执行方法并缓存结果
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
// 模拟从数据库查询
System.out.println("查询数据库: " + id);
return new User(id, "name" + id);
}
// @CacheEvict:清除缓存
// @CacheEvict(value = "users", key = "#id")
// public void deleteUser(Long id) {
// // 删除数据库记录
// }
}
需要在主应用类上添加@EnableCaching
注解启用缓存功能:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
六、配置Redis缓存管理器(可选)
如果需要自定义缓存配置(如过期时间),可配置RedisCacheManager
:
import org.springframework.cache.annotation.EnableCaching;
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;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
// 默认缓存配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)) // 默认10分钟过期
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues();
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.withCacheConfiguration("users", config.entryTtl(Duration.ofHours(1))) // 自定义缓存空间
.build();
}
}
七、Redis事务与管道
RedisTemplate支持事务和管道操作:
// 事务操作示例
redisTemplate.execute(new SessionCallback<Object>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
operations.multi(); // 开启事务
operations.opsForValue().set((K) "key1", (V) "value1");
operations.opsForValue().set((K) "key2", (V) "value2");
return operations.exec(); // 执行事务
}
});
// 管道操作示例(批量执行命令)
List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
for (int i = 0; i < 1000; i++) {
stringRedisConn.set("key" + i, "value" + i);
}
return null;
}
});
八、Redis哨兵与集群配置
如果使用Redis Sentinel或Cluster,需要修改配置:
# Sentinel配置
spring:
redis:
sentinel:
master: mymaster # 主节点名称
nodes: 192.168.1.1:26379,192.168.1.2:26379 # Sentinel节点列表
# Cluster配置
spring:
redis:
cluster:
nodes: 192.168.1.1:7000,192.168.1.2:7001,192.168.1.3:7002 # 集群节点列表
password: yourpassword
九、注意事项
- 序列化问题:
- 默认使用JDK序列化(
JdkSerializationRedisSerializer
),建议使用JSON序列化(如GenericJackson2JsonRedisSerializer
)提高可读性。
- 默认使用JDK序列化(
- 缓存穿透/雪崩/击穿:
- 缓存穿透:查询不存在的数据,可缓存空值或布隆过滤器。
- 缓存雪崩:大量缓存同时过期,可设置随机过期时间。
- 缓存击穿:热点key过期,可使用互斥锁或设置永不过期。
- 性能监控:
- 使用Redis自带的
INFO
命令或第三方工具(如RedisInsight)监控内存使用、QPS等指标。
- 使用Redis自带的
以上代码和配置覆盖了Spring Boot集成Redis的常见场景,你可以根据项目需求选择合适的方式使用Redis。