1. 为什么需要Spring Boot整合Redis?
在开始具体操作之前,我们先聊聊为什么要在Spring Boot项目中引入Redis。Redis作为内存数据库的典型代表,其读写性能远超传统关系型数据库。我曾在电商项目中实测过,同样的查询条件,MySQL需要200ms,而Redis仅需2ms,性能差距达到100倍。
Redis特别适合以下场景:
- 高频访问但更新不频繁的数据(如商品分类、城市列表)
- 需要共享的会话信息(分布式Session)
- 需要原子性操作的计数器(秒杀库存)
- 时效性较强的缓存数据(验证码、临时令牌)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与依赖配置
2.1 开发环境要求
建议使用以下环境组合:
- JDK 17(LTS版本稳定性最佳)
- Spring Boot 3.1.x(注意与JDK版本的兼容性)
- Redis 7.0+(生产环境推荐6.2以上稳定版)
重要提示:Spring Boot 3.x默认要求JDK 17+,如果仍在使用JDK 8,需要降级到Spring Boot 2.7.x版本。
2.2 Maven依赖配置
在pom.xml中添加核心依赖:
xml复制<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>
如果需要使用JSON序列化,额外添加:
xml复制<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
3. 基础配置详解
3.1 配置文件设置
在application.yml中配置Redis连接:
yaml复制spring:
redis:
host: 127.0.0.1
port: 6379
password: yourpassword # 无密码可省略
database: 0 # 默认使用0号库
lettuce:
pool:
max-active: 20 # 最大连接数
max-idle: 10 # 最大空闲连接
min-idle: 5 # 最小空闲连接
max-wait: 2000 # 获取连接最大等待时间(ms)
3.2 自定义RedisTemplate
默认的RedisTemplate使用JDK序列化,可读性差且存在安全问题。建议配置自定义模板:
java复制@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用Jackson2JsonRedisSerializer替换默认序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(om.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(om);
// 设置key和value的序列化规则
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
4. 核心操作实战
4.1 基础数据类型操作
通过RedisTemplate可以进行五种基本数据类型的操作:
java复制@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 字符串操作
public void stringDemo() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set("user:1", "张三"); // 设置值
String name = (String) ops.get("user:1"); // 获取值
ops.increment("counter"); // 自增操作
}
// Hash操作
public void hashDemo() {
HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
ops.put("user:info:1", "name", "李四");
ops.put("user:info:1", "age", 25);
Map<Object, Object> entries = ops.entries("user:info:1");
}
// List操作
public void listDemo() {
ListOperations<String, Object> ops = redisTemplate.opsForList();
ops.leftPush("task:queue", "task1");
ops.rightPush("task:queue", "task2");
Object task = ops.leftPop("task:queue");
}
// Set操作
public void setDemo() {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
ops.add("user:tags:1", "VIP", "NEW_USER");
Set<Object> tags = ops.members("user:tags:1");
}
// ZSet操作
public void zsetDemo() {
ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
ops.add("leaderboard", "player1", 100);
ops.add("leaderboard", "player2", 200);
Set<Object> top3 = ops.range("leaderboard", 0, 2);
}
4.2 事务与管道
Redis支持事务和管道操作,可以显著提升批量操作的性能:
java复制// 事务示例
public void transactionDemo() {
redisTemplate.execute(new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
operations.multi();
operations.opsForValue().set("key1", "value1");
operations.opsForValue().set("key2", "value2");
return operations.exec();
}
});
}
// 管道示例
public void pipelineDemo() {
redisTemplate.executePipelined(new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
for (int i = 0; i < 1000; i++) {
operations.opsForValue().set("pipeline:" + i, "value" + i);
}
return null;
}
});
}
5. 高级特性应用
5.1 发布订阅模式
Redis的Pub/Sub功能可以实现简单的消息系统:
java复制// 配置消息监听容器
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener(listenerAdapter, new PatternTopic("news.*"));
return container;
}
// 消息处理器
@Bean
public MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
// 消息接收者
@Component
public class Receiver {
public void receiveMessage(String message, String channel) {
System.out.println("收到频道[" + channel + "]的消息:" + message);
}
}
// 消息发布
public void publishMessage() {
redisTemplate.convertAndSend("news.tech", "Spring Boot 3.2发布!");
}
5.2 分布式锁实现
利用Redis实现简单的分布式锁:
java复制public boolean tryLock(String lockKey, String requestId, long expireTime) {
return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId,
Duration.ofSeconds(expireTime));
}
public boolean releaseLock(String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else return 0 end";
Long result = redisTemplate.execute(
new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(lockKey),
requestId);
return result != null && result == 1;
}
6. 性能优化与问题排查
6.1 连接池配置建议
生产环境连接池推荐配置:
yaml复制spring:
redis:
lettuce:
pool:
max-active: 50 # 根据QPS调整,建议QPS/100
max-idle: 20
min-idle: 10
max-wait: 1000 # 获取连接超时时间(ms)
time-between-eviction-runs: 30000 # 空闲连接检测周期(ms)
6.2 常见问题解决方案
-
连接超时问题
- 检查防火墙设置
- 适当增加超时时间:
spring.redis.timeout=3000
-
序列化异常
- 确保所有存储的对象实现Serializable接口
- 使用一致的序列化方案
-
内存溢出
- 设置合理的TTL:
redisTemplate.expire(key, 30, TimeUnit.MINUTES) - 监控大Key:
redis-cli --bigkeys
- 设置合理的TTL:
-
缓存穿透防护
java复制public Object getWithPenetrationProtection(String key) { Object value = redisTemplate.opsForValue().get(key); if (value == null) { // 数据库查询 value = getFromDB(key); if (value == null) { // 设置空值缓存 redisTemplate.opsForValue().set(key, "", 5, TimeUnit.MINUTES); } else { redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES); } } return "".equals(value) ? null : value; }
7. 监控与维护
7.1 健康检查配置
Spring Boot Actuator提供Redis健康检查端点:
yaml复制management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: health
访问/actuator/health可查看Redis连接状态。
7.2 可视化工具推荐
- RedisInsight:官方推出的免费可视化工具
- Another Redis Desktop Manager:轻量级开源客户端
- Redisson:Java客户端,提供更多分布式特性
8. 实际项目经验分享
在电商项目中,我们使用Redis实现了以下功能:
-
商品详情缓存
- 缓存结构:Hash存储商品完整信息
- 更新策略:数据库变更后双删(先删缓存再更新DB再删缓存)
-
秒杀系统
- 库存扣减:Lua脚本保证原子性
lua复制local stock = tonumber(redis.call('GET', KEYS[1])) if stock > 0 then redis.call('DECR', KEYS[1]) return 1 end return 0 -
分布式Session
java复制@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) public class SessionConfig { @Bean public RedisSerializer<Object> springSessionDefaultRedisSerializer() { return new GenericJackson2JsonRedisSerializer(); } }
踩过的坑:
- 大Value导致网络阻塞:控制单个Value不超过10KB
- 无限制增长Key:设置合理的过期时间
- 缓存雪崩:采用随机过期时间分散失效时间点
