首页 智能穿戴

Spring Boot Redis 缓存实战:从入门到性能优化全攻略

分类:智能穿戴
字数: (4000)
阅读: (0117)
内容摘要:Spring Boot Redis 缓存实战:从入门到性能优化全攻略,

在现代 Web 应用开发中,性能至关重要。高并发场景下,数据库的压力往往是性能瓶颈。Spring Boot 集成 Redis 缓存解决方案,能有效缓解数据库压力,提升应用响应速度。本文将深入探讨如何在 Spring Boot 项目中高效地集成 Redis 缓存,并分享一些实战经验。

场景重现:数据库压力山大

假设一个电商平台,首页需要展示商品列表。每次用户访问首页,都会查询数据库获取商品信息。在高并发场景下,大量的数据库查询会导致响应时间变慢,甚至出现数据库崩溃的情况。这正是我们需要引入缓存机制来解决的痛点。

Redis 缓存原理深度剖析

Redis (Remote Dictionary Server) 是一个开源的内存数据结构存储系统,可用作数据库、缓存和消息代理。它支持多种数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)与范围查询、 bitmaps、 hyperloglogs 和地理空间(geospatial) 索引半径查询。 Redis 内置了复制(replication),LUA 脚本(Lua scripting), LRU 驱动事件(LRU eviction),事务(transactions) 和不同级别的磁盘持久化(persistence), 并通过 Redis Sentinel 提供高可用性(high availability),并通过 Redis Cluster 自动分区(automatic partitioning)。

缓存的本质就是用空间换时间。将频繁访问的数据存储在高速缓存中,下次访问时直接从缓存中获取,避免了对数据库的频繁查询,从而提高了响应速度。

Spring Boot Redis 缓存实战:从入门到性能优化全攻略

常见的缓存策略包括:

  • Cache Aside (旁路缓存): 应用先从缓存中查询,如果缓存未命中,则从数据库中查询,然后将数据写入缓存。这种策略是最常用的缓存策略。
  • Read Through / Write Through (读穿透/写穿透): 应用直接与缓存交互,缓存负责与数据库交互。读穿透是指应用读取缓存时,如果缓存未命中,缓存会自动从数据库中加载数据并返回给应用。写穿透是指应用写入缓存时,缓存会同时写入数据库。
  • Write Behind (写回): 应用写入缓存后立即返回,缓存异步地将数据写入数据库。这种策略可以提高写入性能,但可能会导致数据不一致。

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

1. 添加 Redis 依赖

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

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

2. 配置 Redis 连接

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

Spring Boot Redis 缓存实战:从入门到性能优化全攻略
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=your_redis_password # 可选
spring.redis.database=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. 使用 @Cacheable@CachePut@CacheEvict 注解

  • @Cacheable: 在方法执行前,Spring 先从缓存中查找结果,如果找到则直接返回,否则执行方法并将结果放入缓存。
  • @CachePut: 每次都会执行方法,并将结果放入缓存。
  • @CacheEvict: 用于从缓存中移除数据。
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @Cacheable(value = "product", key = "#id") // 使用 product 作为缓存名称,id 作为 key
    public Product getProductById(Long id) {
        System.out.println("从数据库中查询商品信息,id: " + id);
        // 模拟从数据库中查询商品信息
        Product product = new Product();
        product.setId(id);
        product.setName("Product " + id);
        product.setPrice(99.99);
        return product;
    }

}

5. RedisTemplate 的使用

Spring Data Redis 提供了 RedisTemplate 类,用于操作 Redis。可以通过 RedisTemplate 进行更灵活的缓存操作,例如设置过期时间、使用不同的序列化器等。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void set(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit); // 设置过期时间
    }

    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void delete(String key) {
        redisTemplate.delete(key);
    }

}

实战避坑:缓存穿透、击穿、雪崩

在使用 Redis 缓存时,需要注意以下几个问题:

Spring Boot Redis 缓存实战:从入门到性能优化全攻略
  • 缓存穿透: 指查询一个不存在的数据,缓存和数据库中都没有。导致每次请求都会穿透到数据库,造成数据库压力。解决方法:
    • 缓存空对象:当数据库中不存在该数据时,缓存一个空对象,并设置较短的过期时间。
    • 使用 Bloom Filter:在缓存之前使用 Bloom Filter 进行过滤,如果 Bloom Filter 判断数据不存在,则直接返回,避免访问缓存和数据库。
  • 缓存击穿: 指一个热点 key 在缓存失效的瞬间,大量的请求同时访问数据库。解决方法:
    • 设置热点 key 永不过期:对于热点 key,可以设置为永不过期。
    • 使用互斥锁:当缓存失效时,使用互斥锁,只允许一个请求访问数据库,其他请求等待。当第一个请求将数据写入缓存后,其他请求直接从缓存中获取数据。
  • 缓存雪崩: 指大量的 key 在同一时间失效,导致大量的请求同时访问数据库。解决方法:
    • 设置不同的过期时间:避免大量的 key 在同一时间失效,可以设置不同的过期时间,例如使用随机过期时间。
    • 使用互斥锁:当缓存失效时,使用互斥锁,只允许少量的请求访问数据库,其他请求等待。
    • 构建多级缓存:使用本地缓存 + Redis 缓存,即使 Redis 缓存失效,本地缓存也能提供一定的保护。

性能优化:选择合适的序列化器

RedisTemplate 默认使用 JdkSerializationRedisSerializer 进行序列化,这种序列化方式会将对象序列化成 Java 对象,占用空间较大,性能较差。建议使用更高效的序列化器,例如:

  • StringRedisSerializer: 用于序列化字符串。
  • GenericJackson2JsonRedisSerializer: 用于序列化 JSON 对象。 推荐使用,通用性强。
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key 采用 String 的序列化方式
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // value 采用 JSON 的序列化方式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // hash key 采用 String 的序列化方式
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); // hash value 采用 JSON 的序列化方式
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}

监控与告警:保障缓存稳定性

需要对 Redis 进行监控,及时发现问题并进行处理。常用的监控指标包括:

  • CPU 使用率
  • 内存使用率
  • 连接数
  • 命中率
  • 慢查询

可以使用 Redis 内置的 INFO 命令获取 Redis 的状态信息。也可以使用 Redis Desktop Manager 等工具进行监控。

Spring Boot Redis 缓存实战:从入门到性能优化全攻略

对于 Nginx 反向代理的场景,需要关注 Nginx 的并发连接数、请求处理时间等指标。可以使用 Nginx 自带的 ngx_http_stub_status_module 模块进行监控。也可以使用宝塔面板等工具进行可视化监控。

设置告警规则,当监控指标超过阈值时,发送告警通知,例如通过邮件、短信等方式。

Spring Boot Redis 缓存实战:从入门到性能优化全攻略

转载请注明出处: 脱发程序员

本文的链接地址: http://m.acea1.store/blog/806202.SHTML

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

()
您可能对以下文章感兴趣
评论
  • 键盘侠本侠 5 天前
    请问一下,如果使用 Redis 集群,配置上有什么需要注意的吗?
  • 云南过桥米线 1 天前
    文章通俗易懂,适合新手入门,点赞! 另外,如果能加上 RedisTemplate 的详细用法就更好了。
  • 奶茶续命 1 天前
    写得真不错,把 Spring Boot 集成 Redis 缓存的流程讲得很清晰,实战避坑部分也很实用,赞一个!
  • 干饭人 2 天前
    序列化器的选择也很重要,之前没注意,用了默认的,现在准备改成 GenericJackson2JsonRedisSerializer 了。