Spring Boot 整合 Redis详解从基础操作到实战应用
作者:igxia
文章介绍了SpringBoot整合Redis的必要性、步骤及核心数据类型,涵盖分布式锁、缓存注解等高级功能,并提供最佳实践如键命名规范和内存优化,强调二者结合提升应用性能与可扩展性,感兴趣的朋友跟随小编一起看看吧
在现代应用中,缓存 几乎是性能优化的必备手段。Redis 作为高性能的内存数据库,不仅支持键值对缓存,还支持丰富的数据结构(如 List、Set、Hash、ZSet 等),被广泛用于缓存、分布式锁、消息队列、计数器等场景。
Spring Boot 提供了开箱即用的 Redis 集成支持,开发者可以非常方便地在项目中使用 Redis。
一、为什么选择 Redis?
在现代应用开发中,Redis 已成为高性能缓存和分布式数据存储的首选方案。作为内存数据结构存储系统,Redis 提供:
- 亚毫秒级响应速度(10万+ QPS)
- 丰富的数据结构支持
- 持久化选项(RDB/AOF)
- 高可用架构(主从复制、哨兵、集群)
Spring Boot 通过 Spring Data Redis 模块提供了与 Redis 的无缝集成,极大简化了开发流程。
二、Spring Boot 整合 Redis 步骤
1. 添加依赖
在 pom.xml
中添加:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <!-- 推荐使用 Jedis 客户端 --> </dependency>
2. 配置 Redis 连接
在 application.yml
中配置:
spring: redis: host: localhost port: 6379 password: your-password # 如果有密码 database: 0 # 默认数据库索引 jedis: pool: max-active: 8 # 连接池最大连接数 max-idle: 8 # 连接池最大空闲连接 min-idle: 2 # 连接池最小空闲连接
3. 配置 RedisTemplate
创建配置类:
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用Jackson序列化器 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); // 设置序列化 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } }
三、Redis 五大核心数据类型
1. String(字符串)
特点:最基本的数据类型,最大能存储 512MB
常用场景:
- 缓存简单值
- 计数器
- 分布式锁
操作示例:
@Autowired private RedisTemplate<String, Object> redisTemplate; // 设置值 redisTemplate.opsForValue().set("user:1001:name", "Alice"); // 获取值 String name = (String) redisTemplate.opsForValue().get("user:1001:name"); // 自增计数器 redisTemplate.opsForValue().increment("article:1001:views"); // 设置带过期时间(30分钟) redisTemplate.opsForValue().set("temp:session", "data", 30, TimeUnit.MINUTES);
2. Hash(哈希)
特点:键值对集合,适合存储对象
常用场景:
- 存储用户资料
- 商品属性
- 配置信息
操作示例:
// 存储用户对象 Map<String, String> userMap = new HashMap<>(); userMap.put("name", "Bob"); userMap.put("age", "30"); userMap.put("email", "bob@example.com"); redisTemplate.opsForHash().putAll("user:1002", userMap); // 获取单个字段 String email = (String) redisTemplate.opsForHash().get("user:1002", "email"); // 更新单个字段 redisTemplate.opsForHash().put("user:1002", "age", "31"); // 获取所有字段 Map<Object, Object> userData = redisTemplate.opsForHash().entries("user:1002");
3. List(列表)
特点:有序、可重复的字符串集合
常用场景:
- 消息队列
- 最新消息排行
- 记录日志
操作示例:
// 从左侧插入 redisTemplate.opsForList().leftPush("news:latest", "Article 1"); redisTemplate.opsForList().leftPush("news:latest", "Article 2"); // 从右侧插入 redisTemplate.opsForList().rightPush("news:latest", "Article 3"); // 获取范围数据(0到10) List<Object> latestNews = redisTemplate.opsForList().range("news:latest", 0, 10); // 列表长度 Long size = redisTemplate.opsForList().size("news:latest"); // 模拟队列消费 Object article = redisTemplate.opsForList().rightPop("news:queue", 10, TimeUnit.SECONDS);
4. Set(集合)
特点:无序、不可重复的元素集合
常用场景:
- 标签系统
- 共同好友
- 唯一访客统计
操作示例:
// 添加元素 redisTemplate.opsForSet().add("article:1001:tags", "tech", "java", "spring"); // 获取所有元素 Set<Object> tags = redisTemplate.opsForSet().members("article:1001:tags"); // 检查元素是否存在 boolean containsJava = redisTemplate.opsForSet().isMember("article:1001:tags", "java"); // 集合运算(交集) Set<Object> commonTags = redisTemplate.opsForSet().intersect( "article:1001:tags", "article:1002:tags" ); // 唯一访客统计 redisTemplate.opsForSet().add("article:1001:visitors", "192.168.1.1"); Long visitors = redisTemplate.opsForSet().size("article:1001:visitors");
5. Sorted Set(有序集合)
特点:带分数排序的Set
常用场景:
- 排行榜
- 带权重的队列
- 范围查询
操作示例:
// 添加带分数的元素 redisTemplate.opsForZSet().add("leaderboard", "player1", 2500); redisTemplate.opsForZSet().add("leaderboard", "player2", 1800); redisTemplate.opsForZSet().add("leaderboard", "player3", 3000); // 获取前3名玩家 Set<ZSetOperations.TypedTuple<Object>> topPlayers = redisTemplate.opsForZSet().reverseRangeWithScores("leaderboard", 0, 2); // 更新分数 redisTemplate.opsForZSet().incrementScore("leaderboard", "player1", 100); // 获取玩家排名(从高到低) Long rank = redisTemplate.opsForZSet().reverseRank("leaderboard", "player2"); // 获取分数段玩家(2000-3000分) Set<Object> players = redisTemplate.opsForZSet().rangeByScore("leaderboard", 2000, 3000);
四、高级功能实战
1. 分布式锁实现
public boolean tryLock(String lockKey, String requestId, long expireTime) { return Boolean.TRUE.equals(redisTemplate.execute((RedisCallback<Boolean>) connection -> { // 使用SET命令的NX(不存在才设置)和PX(毫秒过期)选项 String result = connection.set( lockKey.getBytes(), requestId.getBytes(), Expiration.milliseconds(expireTime), RedisStringCommands.SetOption.SET_IF_ABSENT ); return "OK".equals(result); })); } 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"; return Boolean.TRUE.equals(redisTemplate.execute( new DefaultRedisScript<>(script, Long.class), Collections.singletonList(lockKey), requestId )); }
2. 缓存注解使用
@Cacheable(value = "users", key = "#id") public User getUserById(Long id) { // 数据库查询逻辑 return userRepository.findById(id).orElse(null); } @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { // 更新数据库 return userRepository.save(user); } @CacheEvict(value = "users", key = "#id") public void deleteUser(Long id) { userRepository.deleteById(id); }
3. 发布/订阅模式
// 配置消息监听容器 @Bean public RedisMessageListenerContainer container( RedisConnectionFactory factory, MessageListenerAdapter listenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(factory); container.addMessageListener(listenerAdapter, new PatternTopic("news.*")); return container; } // 消息处理器 @Component public class RedisMessageListener { @Autowired private SimpMessagingTemplate messagingTemplate; public void handleMessage(String message, String channel) { // 处理消息并转发到WebSocket messagingTemplate.convertAndSend("/topic/" + channel, message); } } // 发布消息 public void publish(String channel, String message) { redisTemplate.convertAndSend(channel, message); }
五、最佳实践与注意事项
- 键命名规范
- 使用冒号分隔层级:
业务:类型:ID
- 示例:
user:session:1001
,product:info:2005
- 使用冒号分隔层级:
- 内存优化
- 控制单个Value大小(<100KB)
- 使用Hash压缩存储小对象
- 设置合理的TTL
- 性能调优
spring: redis: jedis: pool: max-active: 50 # 根据负载调整 max-wait: 200ms
- 高可用方案
- 开发环境:单节点
- 生产环境:Redis Sentinel 或 Cluster
- 监控指标
// 获取Redis指标 @Autowired private RedisConnectionFactory factory; public void monitor() { RedisConnection connection = factory.getConnection(); Properties info = connection.info(); System.out.println("内存使用: " + info.getProperty("used_memory_human")); System.out.println("连接数: " + info.getProperty("connected_clients")); }
六、总结
Spring Boot 与 Redis 的结合为开发者提供了强大的数据缓存和处理能力。通过掌握:
- 五大核心数据类型的适用场景和操作方法
- RedisTemplate 的高级用法
- 分布式锁、发布订阅等高级功能
- 生产环境最佳实践
到此这篇关于Spring Boot 整合 Redis详解从基础操作到实战应用的文章就介绍到这了,更多相关Spring Boot 整合 Redis内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!