首页 短视频

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)

分类:短视频
字数: (8175)
阅读: (5846)
内容摘要:Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验),

在现代高并发应用中,缓存是提升系统性能的关键手段之一。本文将深入探讨如何在 Spring Boot 项目中整合 Redis 缓存,以应对高流量、低延迟的业务场景。我们将从原理分析、代码实战到常见问题避坑,提供一份全面的 Redis 缓存解决方案。

缓存策略选择:Redis 缓存的优势

缓存策略的选择至关重要。常见的缓存包括本地缓存(如 ConcurrentHashMap、Caffeine)和分布式缓存(如 Redis、Memcached)。本地缓存访问速度快,但受限于单机容量,不适合存储大量数据,且无法解决分布式场景下的数据一致性问题。分布式缓存则可以提供更大的容量和更高的并发性能,但也引入了网络延迟等因素。

Redis 作为一种高性能的 key-value 存储系统,具有以下优势,使其成为 Spring Boot 整合缓存的理想选择:

  • 速度快:Redis 基于内存存储,读写速度极快,可以有效降低数据库压力。
  • 丰富的数据结构:Redis 支持 String、List、Set、Hash、ZSet 等多种数据结构,可以满足各种业务场景的需求。
  • 持久化:Redis 支持 RDB 和 AOF 两种持久化方式,可以保证数据不丢失。
  • 分布式特性:Redis 支持主从复制、哨兵模式和集群模式,可以构建高可用、高并发的分布式缓存系统。

Spring Boot 集成 Redis 缓存:配置与代码实现

1. 添加 Redis 依赖

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)

pom.xml 文件中添加 Spring Data Redis 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- Spring Boot 3.0+ 需要 Lettuce 连接池 -->
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
</dependency>

2. 配置 Redis 连接信息

application.propertiesapplication.yml 文件中配置 Redis 连接信息:

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)
spring:
  redis:
    host: 127.0.0.1 # Redis 服务器地址
    port: 6379 # Redis 服务器端口
    password: # Redis 密码(如果设置了密码)
    database: 0 # Redis 数据库索引,默认为 0

3. 启用缓存支持

在 Spring Boot 启动类或配置类上添加 @EnableCaching 注解,启用缓存支持:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching // 启用缓存支持
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

4. 使用缓存注解

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)

在需要缓存的方法上使用 @Cacheable@CachePut@CacheEvict 等注解来声明缓存策略:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id") // 将方法返回值缓存到名为 "users" 的缓存中,key 为方法参数 id
    public User getUserById(Long id) {
        // 模拟从数据库查询用户
        System.out.println("从数据库查询用户,id = " + id);
        return new User(id, "张三", 20);
    }

}

5. 自定义 RedisTemplate

Spring Boot 默认提供了 RedisTemplate,但其默认的序列化方式是 JdkSerializationRedisSerializer,效率较低。建议自定义 RedisTemplate,使用更高效的序列化方式,例如 StringRedisSerializer 或 Jackson2JsonRedisSerializer:

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key 采用 String 的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash 的 key 也采用 String 的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value 采用 jackson 的序列化方式
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash 的 value 采用 jackson 的序列化方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

实战避坑:常见问题与解决方案

  • 缓存穿透:当查询一个不存在的数据时,缓存和数据库都无法命中,导致请求直接打到数据库,可能造成数据库压力过大。解决方案:
    • 缓存空对象:即使数据库中不存在该数据,也缓存一个空对象(例如 null),并设置较短的过期时间。
    • 布隆过滤器:在缓存之前使用布隆过滤器进行过滤,只有在布隆过滤器中存在的数据才查询缓存。
  • 缓存击穿:当一个热点 key 过期时,大量的请求同时访问该 key,导致请求直接打到数据库,可能造成数据库压力过大。解决方案:
    • 设置永不过期:对于热点 key,可以设置为永不过期,或者使用逻辑过期。
    • 互斥锁:当缓存失效时,使用互斥锁来保证只有一个线程可以查询数据库,并将结果写入缓存。
  • 缓存雪崩:当大量的 key 同时过期时,大量的请求同时访问数据库,可能造成数据库压力过大。解决方案:
    • 设置不同的过期时间:为不同的 key 设置不同的过期时间,避免大量 key 同时过期。
    • 使用二级缓存:在本地缓存中缓存热点数据,减轻 Redis 的压力。
  • 数据一致性问题:当数据库中的数据发生变化时,需要及时更新缓存,以保证数据一致性。解决方案:
    • Cache Aside Pattern:先更新数据库,再删除缓存。
    • Read/Write Through Pattern:应用程序直接与缓存交互,缓存负责更新数据库。
    • 使用 Canal 等工具监听数据库变更,异步更新缓存:利用消息队列等机制,实现最终一致性。

在实际项目中,可以结合具体的业务场景选择合适的缓存策略和解决方案。同时,需要注意监控 Redis 的性能指标,例如 CPU 使用率、内存使用率、QPS 等,及时发现和解决问题。另外,生产环境中,推荐使用 Redis 集群模式,提高可用性和扩展性,并利用如 Nginx 的反向代理和负载均衡能力,优化用户访问体验。

总结

本文详细介绍了 Spring Boot 整合 Redis 缓存的步骤和常见问题的解决方案。通过合理的缓存策略,可以有效提升系统的性能和可用性,为用户提供更好的体验。希望本文能帮助读者更好地理解和应用 Redis 缓存。

Spring Boot 缓存利器:Redis 整合实战指南(附避坑经验)

转载请注明出处: 半杯凉茶

本文的链接地址: http://m.acea2.store/blog/244674.SHTML

本文最后 发布于2026-04-15 23:54:48,已经过了11天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 秃头程序员 2 天前
    关于缓存穿透、击穿和雪崩的解决方案讲得很到位,学习了。
  • 西红柿鸡蛋面 4 天前
    请问一下,如果使用 Canal 监听数据库变更,更新缓存的顺序是先删除缓存还是先更新缓存?
  • 格子衫青年 6 天前
    关于缓存穿透、击穿和雪崩的解决方案讲得很到位,学习了。
  • 干饭人 5 天前
    请问一下,如果使用 Canal 监听数据库变更,更新缓存的顺序是先删除缓存还是先更新缓存?