摘要
- 本文介绍 SpringBoot 集成 Redis 的方法
- 本文基于
redis-7.4.7,springboot-3.5.8
- Redis官网:https://redis.io/
引入依赖
xml
复制代码
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.5.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis 连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
配置 application.yml
单机模式
yml
复制代码
spring:
data:
redis:
host: 127.0.0.1
port: 6379
database: 0
username: admin
password: redis123
timeout: 5s
connectTimeout: 3s
clientName: demo-service
lettuce:
shutdown-timeout: 100ms
pool:
max-active: 64
max-idle: 32
min-idle: 16
max-wait: 2s
time-between-eviction-runs: 30s
| 配置项 |
示例值 |
含义 |
默认值 |
生产建议 |
spring.data.redis.host |
localhost |
Redis 服务地址(IP / 域名) |
localhost |
生产使用内网 IP / 域名 |
spring.data.redis.port |
6379 |
Redis 服务端口 |
6379 |
一般无需修改 |
spring.data.redis.username |
admin |
Redis ACL 用户名(Redis 6+) |
(空) |
未启用 ACL 可不配置 |
spring.data.redis.password |
123456 |
Redis 访问密码 |
(空) |
生产必须配置 |
spring.data.redis.database |
0 |
逻辑数据库索引(0--15) |
0 |
Cluster 模式无效 |
spring.data.redis.timeout |
3s |
Redis 命令执行超时 |
60s(依版本) |
建议 2--5s |
spring.data.redis.connect-timeout |
3s |
TCP 建连超时 |
OS 默认 |
建议 1--5s |
spring.data.redis.client-name |
my-redis-client |
客户端标识,用于运维定位 |
(空) |
强烈建议配置 |
| 配置项 |
示例值 |
含义 |
默认值 |
生产建议 |
spring.data.redis.lettuce.pool.max-active |
8 |
连接池最大连接数(使用中 + 空闲) |
8 |
CPU × 2~4 或压测评估 |
spring.data.redis.lettuce.pool.max-wait |
2s |
连接耗尽时等待时间 |
-1(无限等待) |
必须设置,1--3s |
spring.data.redis.lettuce.pool.max-idle |
8 |
最大空闲连接数 |
8 |
max-active × 30%~50% |
spring.data.redis.lettuce.pool.min-idle |
0 |
最小空闲连接数 |
0 |
≥ max-active × 25% |
spring.data.redis.lettuce.pool.time-between-eviction-runs |
60s |
空闲连接检测周期 |
-1(不启用) |
30--60s |
| 配置项 |
示例值 |
含义 |
默认值 |
生产建议 |
spring.data.redis.lettuce.shutdown-timeout |
100ms |
应用关闭时等待连接释放时间 |
100ms |
一般无需修改 |
sentinel 模式
yml
复制代码
spring:
data:
redis:
database: 0
username: admin
password: redis123
timeout: 5s
connectTimeout: 3s
clientName: demo-service
sentinel:
master: mymaster
nodes:
- 10.0.0.10:26379
- 10.0.0.11:26379
- 10.0.0.12:26379
lettuce:
shutdown-timeout: 100ms
pool:
max-active: 64
max-idle: 32
min-idle: 16
max-wait: 2s
time-between-eviction-runs: 30s
| 配置项 |
示例值 |
含义 |
是否必填 |
说明 |
spring.data.redis.sentinel.master |
mymaster |
Sentinel 监控的 Master 名称 |
✅ |
必须与 Sentinel monitor 名称完全一致 |
spring.data.redis.sentinel.nodes |
10.0.0.10:26379,10.0.0.11:26379,10.0.0.12:26379 |
Sentinel 节点列表 |
✅ |
至少配置 2--3 个 Sentinel,提升可用性 |
spring.data.redis.sentinel.username |
(空) |
Sentinel 的认证用户名 |
|
如果启用 ACL,则必填 |
spring.data.redis.sentinel.password |
(空) |
Sentinel 的认证密码 |
|
如果启用 ACL,则必填 |
cluster 模式
yml
复制代码
spring:
data:
redis:
username: admin
password: redis123
timeout: 5s
connectTimeout: 3s
clientName: order-service
cluster:
nodes:
- 192.168.1.10:6379
- 192.168.1.11:6379
- 192.168.1.12:6379
lettuce:
shutdown-timeout: 100ms
cluster:
refresh:
adaptive: true
period: 10s
pool:
max-active: 64
max-idle: 32
min-idle: 16
max-wait: 2s
time-between-eviction-runs: 30s
bash
复制代码
集群模式下,不能配置 `spring.data.redis.database`,因为集群只能使用默认数据库索引 0
| 配置项 |
示例值 |
含义 |
是否必填 |
默认值 |
生产建议 |
spring.data.redis.cluster.nodes |
192.168.1.10:6379,... |
Redis Cluster 节点地址列表 |
✅ |
(空) |
至少配置 3 个节点 |
- Cluster 拓扑自动刷新配置,用于解决集群拓扑变化时 Client 无法自动感知
| 配置项 |
示例值 |
含义 |
默认值 |
是否推荐 |
adaptive |
true |
开启 事件驱动拓扑刷新 |
false |
✅ 必须 |
period |
10s |
开启 定时拓扑刷新周期 |
关闭 |
✅ 必须 |
SpringBoot 配置类
封装 RedisTemplate
java
复制代码
package com.example.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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 ObjectMapper redisObjectMapper() {
return JsonMapper.builder()
.addModule(new JavaTimeModule())
.serializationInclusion(JsonInclude.Include.NON_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();
}
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory,
ObjectMapper objectMapper) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// --- Key 序列化 ---
StringRedisSerializer stringSerializer = new StringRedisSerializer();
// --- Value 序列化 ---
// 使用 Jackson JSON,避免 JDK 序列化性能与安全问题
GenericJackson2JsonRedisSerializer jsonSerializer =
new GenericJackson2JsonRedisSerializer(objectMapper);
// Key
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// Value
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
}
开启注解式缓存
java
复制代码
package com.example.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@AutoConfigureAfter(value = RedisConfig.class)
//注入redis分组配置属性:ttlmap
@ConfigurationProperties(prefix = "caching")
public class RedisCachingConfig {
/**
* 分组配置项
*/
@Getter
@Setter
private Map<String, Long> ttlmap;
@Bean
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()))
//缺省配置
.cacheDefaults(redisCacheConfiguration(redisTemplate, 3600L))
//分组配置,不需要分组配置可以去掉,不同的组配置不同的缓存过期时间,可以防止"缓存雪崩"
.withInitialCacheConfigurations(initialRedisCacheConfiguration(redisTemplate))
.build();
}
/**
* 缺省缓存配置
*/
private RedisCacheConfiguration redisCacheConfiguration(RedisTemplate<String, Object> redisTemplate, Long ttl) {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl)) //设置过期,单位秒
//.disableCachingNullValues() //不允许存储null值,默认可以存储null,缓存null可以防止"缓存穿透"
//.disableKeyPrefix() //设置key前面不带前缀,最好不要去掉前缀,否则执行删除缓存时会清空全部缓存
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getStringSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
}
/**
* 针对不同的缓存组配置不同的设置
*/
private Map<String, RedisCacheConfiguration> initialRedisCacheConfiguration(RedisTemplate<String, Object> redisTemplate) {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
for (Map.Entry<String, Long> entry : ttlmap.entrySet()) {
redisCacheConfigurationMap.put(entry.getKey(), redisCacheConfiguration(redisTemplate, entry.getValue()));
}
return redisCacheConfigurationMap;
}
}
yaml
复制代码
caching:
ttlmap:
commonCache: 3600
loginCache: 7200
java
复制代码
@EnableCaching
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
java
复制代码
@Service
// 缓存分组
@CacheConfig(cacheNames = "commonCache")
public class SystemUserServiceImpl implements ISystemUserService {
@Autowired
SystemUserJpaRepository systemUserJpaRepository;
//向组内添加缓存
@Cacheable(key = "'SystemUserServiceImpl.findAll'")
public List<SystemUser> findAll() {
List<SystemUser> systemUserList = systemUserJpaRepository.findAll();
return systemUserList;
}
//向组内添加缓存
@Cacheable(key = "'SystemUserServiceImpl.findById_'+ #userId")
public SystemUser findById(String userId) {
return systemUserJpaRepository.findById(userId);
}
// 删除组内指定缓存
@CacheEvict(key = "'SystemUserServiceImpl.findById_'+ #userId")
public void deleteById(String userId) {
return systemUserJpaRepository.deleteById(userId);
}
// 删除本组全部缓存
@CacheEvict(allEntries = true, beforeInvocation = true)
public SystemUser add(SystemUser user) {
systemUserJpaRepository.save(user);
return user;
}
}