简介:本文详细介绍Spring Boot如何整合NoSQL数据库Redis,涵盖依赖配置、核心API使用、序列化优化、集群部署及高并发场景实践,帮助开发者快速构建高性能缓存系统。
在分布式系统和高并发场景下,传统关系型数据库(如MySQL)面临性能瓶颈,而Redis作为高性能的内存数据库,凭借其数据结构丰富、响应速度快、支持持久化等特性,成为Spring Boot应用中理想的缓存层选择。通过Redis缓存热点数据,可显著降低数据库压力,提升系统吞吐量。
docker run -d --name redis -p 6379:6379 redis:6.2.6 redis-server --requirepass "yourpassword"
在pom.xml中引入Spring Data Redis和Lettuce(默认连接池)依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 可选:用于JSON序列化 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
在application.yml中配置连接参数:
spring:redis:host: localhostport: 6379password: yourpassworddatabase: 0 # 默认使用DB0lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: -1ms # 无等待限制
默认的JDK序列化存在性能问题,推荐使用JSON序列化:
@Configurationpublic class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 使用Jackson2JsonRedisSerializer替代JDK序列化Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);serializer.setObjectMapper(mapper);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);template.afterPropertiesSet();return template;}}
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 字符串操作public void stringOps() {// 设置带过期时间的Key(10分钟)redisTemplate.opsForValue().set("user:1001", "Alice", 10, TimeUnit.MINUTES);// 原子性递增redisTemplate.opsForValue().increment("counter", 1);}// Hash操作(适合存储对象)public void hashOps() {Map<String, Object> userMap = new HashMap<>();userMap.put("name", "Bob");userMap.put("age", 30);redisTemplate.opsForHash().putAll("user:1002", userMap);Object age = redisTemplate.opsForHash().get("user:1002", "age");}
public boolean tryLock(String lockKey, String requestId, long expireTime) {Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.SECONDS);return Boolean.TRUE.equals(result);}public void unlock(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";redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(lockKey),requestId);}
public User getUserWithCachePenetrationProtection(Long userId) {String cacheKey = "user:" + userId;// 1. 先从缓存查询User user = (User) redisTemplate.opsForValue().get(cacheKey);if (user != null) {return user;}// 2. 缓存空对象(设置短过期时间)if (Boolean.TRUE.equals(redisTemplate.hasKey(cacheKey + ":null"))) {return null;}// 3. 查询数据库user = userDao.findById(userId);if (user == null) {// 缓存空标记(5秒过期)redisTemplate.opsForValue().set(cacheKey + ":null", "", 5, TimeUnit.SECONDS);return null;}// 4. 写入缓存(1小时)redisTemplate.opsForValue().set(cacheKey, user, 1, TimeUnit.HOURS);return user;}
当使用Redis集群时,需修改配置:
spring:redis:cluster:nodes:- 192.168.1.100:6379- 192.168.1.101:6379- 192.168.1.102:6379max-redirects: 3 # 最大重定向次数
连接池调优:
CPU核心数 * 2 + 1CPU核心数Pipeline批量操作:
public void batchInsert(List<User> users) {redisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (User user : users) {connection.stringCommands().set(("user:" + user.getId()).getBytes(),objectMapper.writeValueAsBytes(user));}return null;});}
监控指标:
keys * / (keys * + misses *)INFO memoryINFO clients连接超时:
spring.redis.timeout配置(默认2秒)序列化异常:
Serializable接口Key冲突:
项目名:业务名:ID)RedisKeyPrefix接口自定义前缀Spring Boot整合Redis的核心价值在于通过声明式编程简化缓存操作,开发者应重点关注:
通过本文介绍的整合方案,可快速构建支持每秒数万次请求的高性能缓存系统,为分布式应用提供稳定的数据访问层。实际开发中建议结合Spring Cache抽象层进一步简化代码,同时通过Redis Sentinel或Cluster保障高可用性。