你在开发 Spring Boot3 项目时,有没有遇到过这样的困扰?随着项目功能不断增加,数据量逐渐庞大,接口响应速度变得越来越慢,用户体验直线下降。好不容易找到优化方向 —— 引入 Redis 缓存,可在实际使用 Spring Boot3 与 Redis 整合的缓存注解时,却发现状况百出:缓存数据不生效、缓存更新不及时,甚至出现数据不一致的情况…… 别着急,这篇文章就是来帮你解决这些问题的!
开启缓存功能的第一步:@EnableCaching 注解
在使用缓存注解前,有一个关键步骤千万不能忘,那就是在 Spring Boot3 项目的主应用类或者配置类上加上@EnableCaching注解。这就好比打开缓存世界的大门,只有加上这个注解,后续的缓存注解才能生效。
例如,在你的 Spring Boot3 项目主类Application.java中,只需要添加一行代码:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这样,Spring Boot3 项目就开启了缓存功能,为后续使用缓存注解做好了准备。
核心缓存注解详解
@Cacheable:查询场景的好帮手
@Cacheable注解用于标记一个方法的结果应该被缓存。当该方法被调用时,Spring 会先检查缓存中是否已经存在对应的结果,如果存在,就直接从缓存中返回数据,不再执行方法体,这样能大大减少数据库查询等耗时操作。
比如在一个用户管理模块中,我们有一个查询用户信息的方法:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Cacheable(value = "user", key = "#p0.id")
public User getUserById(User user) {
// 这里原本可能是从数据库查询用户信息的逻辑
// 假设通过复杂的SQL查询从数据库获取用户
return userRepository.findById(user.getId()).orElse(null);
}
}
这里的value指定了缓存的名称为 “user”,key = "#p0.id"则表示以方法第一个参数user的id属性作为缓存的键。也就是说,当你第一次调用getUserById方法查询某个用户信息时,结果会被存入 “user” 缓存中,之后再查询相同用户信息,就可以直接从缓存获取,无需再次执行从数据库查询的方法。
@CachePut:数据更新的守护者
@CachePut注解与@Cacheable有所不同。@CachePut是在方法执行后将返回值放入缓存,它不管缓存中是否已经存在数据,都会执行方法,然后将执行结果更新到缓存中。
这在数据更新场景非常有用,比如用户修改了个人信息。我们可以在更新用户信息的方法上加上@CachePut注解:
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@CachePut(value = "user", key = "#p0.id")
public User updateUser(User user) {
// 这里是更新用户信息到数据库的逻辑
User updatedUser = userRepository.save(user);
return updatedUser;
}
}
这样每次修改用户信息后,缓存中的用户信息也会随之更新,保证了缓存数据与数据库数据的一致性。
@CacheEvict:缓存清理大师
@CacheEvict注解主要用于在数据修改或删除时,移除缓存中的旧数据。当你删除某个用户信息时,为了避免后续查询还从缓存中获取到已经删除的数据,就可以在删除方法上添加@CacheEvict注解:
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@CacheEvict(value = "user", key = "#p0.id")
public void deleteUser(User user) {
userRepository.delete(user);
}
}
这样就能精准地清除缓存中对应的数据;如果你想清空整个 “user” 缓存空间的数据,使用@CacheEvict(value = "user", allEntries = true)即可:
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@CacheEvict(value = "user", allEntries = true)
public void clearUserCache() {
// 这里可以添加一些清理缓存前的业务逻辑
}
}
缓存注解使用进阶技巧
除了掌握这些基本的缓存注解使用方法,在实际开发中,还有一些小技巧能让你更好地使用缓存注解。
合理设置缓存过期时间
为了避免缓存数据长期不更新导致数据陈旧,我们可以为缓存设置过期时间。在@Cacheable、@CachePut等注解中,可以通过cacheManager结合配置类来设置。
例如,在配置类中定义一个缓存管理器,并设置缓存的过期时间:
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5)) // 设置缓存过期时间为5分钟
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
}
应对缓存穿透、缓存雪崩等问题
缓存穿透是指查询一个一定不存在的数据,由于缓存不命中,每次都要去数据库查询,给数据库带来巨大压力。可以通过布隆过滤器等方式来过滤掉非法请求。
缓存雪崩是指大量缓存集中在同一时间失效,导致大量请求直接访问数据库。可以通过设置不同的缓存过期时间,避免缓存集体失效;也可以使用 Redis 的哨兵模式、集群模式来提高系统的可用性和稳定性。
总结
通过对 Spring Boot3 整合 Redis 的缓存注解的学习,相信你已经对如何优化项目性能有了更清晰的思路。从开启缓存功能的@EnableCaching注解,到核心的@Cacheable、@CachePut、@CacheEvict注解,再到使用缓存注解的进阶技巧,每一个环节都至关重要。
现在,不妨回到你的项目中,按照这些方法实践起来!如果你在使用过程中遇到了其他问题,或者有更好的经验和技巧,欢迎在评论区留言分享,大家一起交流学习,共同打造高性能的 Spring Boot3 项目!