Spring Boot 集成 Redis 实战总结
一、基础集成与配置
-
依赖引入
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
- 默认使用 Lettuce 作为连接池(优于 Jedis,支持异步和 Reactive 编程)。
-
配置文件
spring: redis: host: localhost port: 6379 password: 123456 database: 0 lettuce: pool: max-active: 16 # 最大连接数 max-idle: 8 # 最大空闲连接 min-idle: 2 # 最小空闲连接
-
序列化配置
默认的RedisTemplate
使用 JDK 序列化(可读性差),推荐自定义序列化:@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用 Jackson2JsonRedisSerializer template.setDefaultSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); return template; } }
二、实战使用场景
-
基础操作(字符串、哈希、列表)
@Autowired private RedisTemplate<String, Object> redisTemplate; // 字符串 redisTemplate.opsForValue().set("key", "value", 60, TimeUnit.SECONDS); Object value = redisTemplate.opsForValue().get("key"); // 哈希 redisTemplate.opsForHash().put("user:1", "name", "John"); String name = (String) redisTemplate.opsForHash().get("user:1", "name"); // 列表 redisTemplate.opsForList().leftPush("tasks", "task1"); List<Object> tasks = redisTemplate.opsForList().range("tasks", 0, -1);
-
发布订阅
// 发布端 redisTemplate.convertAndSend("channel", "message"); // 订阅端 @Component public class RedisMessageListener implements MessageListener { @Override public void onMessage(Message message, byte[] pattern) { System.out.println("收到消息: " + new String(message.getBody())); } }
-
分布式锁
使用 Redisson 或手动实现:public boolean tryLock(String key, String value, long expireTime) { return Boolean.TRUE.equals( redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS) ); } public void unlock(String key) { redisTemplate.delete(key); }
三、常用技巧
-
缓存注解
使用@Cacheable
、@CacheEvict
简化缓存逻辑:@Cacheable(value = "users", key = "#userId", unless = "#result == null") public User getUserById(Long userId) { // 查询数据库 } @CacheEvict(value = "users", key = "#userId") public void updateUser(User user) { // 更新数据库 }
-
Pipeline 批量操作
减少网络开销:List<Object> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> { for (int i = 0; i < 100; i++) { connection.stringCommands().set(("key" + i).getBytes(), ("value" + i).getBytes()); } return null; });
-
Lua 脚本
实现原子性操作(如限流):String script = "local count = redis.call('incr', KEYS[1]) " + "if count == 1 then redis.call('expire', KEYS[1], ARGV[1]) end " + "return count"; RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class); Long count = redisTemplate.execute(redisScript, Collections.singletonList("rate_limit:api1"), 60);
四、性能优化
-
连接池调优
- 根据并发量调整
max-active
和max-idle
,避免频繁创建连接。 - 监控连接池指标(如
active
、idle
)防止资源耗尽。
- 根据并发量调整
-
避免大 Key 和热 Key
- 大 Key:拆分数据(如哈希拆分为多个字段)。
- 热 Key:本地缓存 + 随机过期时间,或使用 Redis Cluster 分散压力。
-
合理选择数据结构
- 统计 UV:HyperLogLog(省内存)。
- 排行榜:ZSet。
- 短链接映射:String。
-
过期时间随机化
防止缓存雪崩:int expireTime = 3600 + new Random().nextInt(600); // 3600~4200秒 redisTemplate.expire("key", expireTime, TimeUnit.SECONDS);
-
异步删除
对于大 Key 删除,使用UNLINK
替代DEL
:redisTemplate.unlink("largeKey");
-
监控与日志
- 开启 Redis 慢查询日志:
slowlog-log-slower-than 10000
(单位:微秒)。 - 使用 Prometheus + Grafana 监控 Redis 性能指标(QPS、内存、命中率)。
- 开启 Redis 慢查询日志:
五、常见问题
- 缓存穿透
- 方案:空值缓存 + 布隆过滤器。
- 缓存击穿
- 方案:互斥锁(如 Redis SETNX)。
- 数据一致性
- 方案:延迟双删、订阅 Binlog 异步更新。
六、高级扩展
- Redisson:实现分布式锁、限流器、延迟队列。
- Spring Cache Reactive:响应式编程支持。
- Redis Cluster:集群模式下注意
hash tag
分片优化。
通过合理配置和优化,Spring Boot 集成 Redis 可以实现高性能、高可用的缓存与分布式服务。