文章目录
前言
在Spring Boot项目中引入Redis作为缓存机制,并使用@Cacheable注解来简化缓存的操作,是一个常见且高效的实践。下面,我将概述如何在Spring Boot项目中引入Redis作为缓存,并展示如何使用@Cacheable注解。
基础篇参照:Spring Boot x Redis:零基础入门,性能飙升的实战秘籍!
一、Spring Boot 集成 Redis
1.添加依赖
首先,你需要在你的pom.xml(如果你使用的是Maven)或build.gradle(如果你使用的是Gradle)文件中添加Spring Boot的Redis Starter依赖。
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 如果你需要使用Spring Cache的抽象层,则还需要添加 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.配置Redis
在application.yml文件中配置Redis服务器的连接信息。
application.yml 示例:
spring:
redis:
host: localhost
port: 6379
# password: yourpassword
jedis:
pool:
max-active: 8
# 其他连接池配置...
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 YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
@EnableCaching 注解开启了缓存支持,RedisCacheManager 用来配置 Redis 缓存管理器。
二、Spring Cache 缓存管理器
Spring Cache 缓存管理器(CacheManager)在Spring框架中扮演着重要的角色,它负责管理和维护各种缓存(Cache)组件。
CacheManager 是 Spring Cache 提供的缓存管理的抽象接口,它屏蔽了不同缓存实现之间的差异,提供了统一的访问接口。
CacheManager 主要负责缓存的创建、配置、获取和销毁等操作。通过它,开发者可以轻松地切换不同的缓存实现,如 Redis、EhCache、Caffeine 等,而无需修改业务代码。
1.创建 Spring Cache 缓存管理器
要使用缓存,我们需要配置一个缓存管理器。
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存默认过期时间为1小时
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfig)
.build();
}
}
2.配置缓存策略
我们可以配置不同的缓存策略,比如过期时间。
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30)); // 默认过期时间30分钟
RedisCacheConfiguration usersCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(6)); // users缓存过期时间6小时
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put("users", usersCacheConfig);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(defaultConfig)
.withInitialCacheConfigurations(cacheConfigurations)
.build();
}
这个配置定义了默认缓存过期时间为30分钟,而 users 缓存过期时间为6小时。
3.自定义缓存实现
你也可以自定义缓存实现,以适应特殊需求。
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.disableCachingNullValues(); // 不缓存null值
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(defaultConfig)
.build();
}
缓存策略被设置为不缓存 null 值。
三、缓存过期策略
1.基于时间的过期
在 Redis 中,你可以为缓存设置一个 TTL(Time-To-Live)。
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)); // 过期时间为10分钟
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfig)
.build();
}
2.基于访问次数的过期
可以通过编写自定义逻辑来实现基于访问次数的缓存过期策略。
@Component
public class CustomCacheManager {
private final Map<String, Integer> accessCountMap = new ConcurrentHashMap<>();
public void put(String key, Object value) {
accessCountMap.put(key, 0);
// 这里将对象放入缓存,比如 Redis
}
public Object get(String key) {
Integer count = accessCountMap.get(key);
if (count != null) {
accessCountMap.put(key, count + 1);
if (count + 1 > MAX_ACCESS_COUNT) {
evict(key);
return null;
}
}
// 从缓存中取对象
return null; // 返回缓存对象
}
public void evict(String key) {
accessCountMap.remove(key);
// 从缓存中删除对象
}
}
3.基于空闲时间的过期
设置缓存项在一定时间内未被访问时过期。
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5)) // 过期时间为5分钟
.disableCachingNullValues(); // 不缓存null值
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfig)
.build();
}
4.缓存击穿
缓存击穿是指缓存中某个热点数据失效,导致大量请求同时访问数据库,给数据库造成巨大压力,甚至导致系统崩溃,就像雪崩一样,来势汹汹。
解决方案:
- 使用互斥锁:当缓存数据失效时,只有一个线程可以访问数据库,其他线程等待,就像排队一样,井然有序!
- 设置热点数据永不过期:对于一些访问频率非常高的数据,可以设置永不过期,就像明星一样,永远闪耀!
5.缓存穿透
缓存穿透是指恶意用户不断请求缓存中不存在的数据,导致所有请求都落到数据库上,给数据库造成巨大压力,就像敌人的炮弹一样,精准打击。
解决方案:
- 缓存空值:对于查询数据库返回为空的结果,也将其缓存起来,并设置较短的过期时间,就像设置陷阱一样,迷惑敌人!
- 使用布隆过滤器:布隆过滤器可以快速判断一个元素是否存在于一个集合中,可以用来拦截恶意请求,就像设置一道防护墙一样,保护数据库!
四、基于注解的缓存
1.@Cacheable 注解
@Cacheable 是一个神奇的注解,它会帮你自动缓存方法的返回结果。下次调用这个方法时,如果参数一样,Spring 就不会再执行这个方法,而是直接从缓存里取值。
@Service
public class UserService {
@Cacheable(value = "users", key = "#userId")
public User getUserById(Long userId) {
// 假装我们从数据库里取数据
return userRepository.findById(userId).orElse(null);
}
}
getUserById 方法会把结果缓存到 Redis 里的 users 键下,键名是 userId 的值。
2.@CacheEvict 注解
@CacheEvict 用来清除缓存。当你更新或删除数据时,缓存也需要同步更新。
@Service
public class UserService {
@CacheEvict(value = "users", key = "#userId")
public void deleteUser(Long userId) {
// 删除了数据库里的数据,同时删除了缓存中数据
userRepository.deleteById(userId);
}
}
调用 deleteUser 方法时,会自动清除 Redis 中 users 键下对应 userId 的缓存。
3.@CachePut 注解
@CachePut是用来更新缓存的,它不会影响方法的实际调用。
@Service
public class UserService {
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
// 假装我们更新了数据库里的数据
return userRepository.save(user);
}
}
每次调用 updateUser 方法时,都会把返回的 User 对象更新到缓存里。
注:所有Spring Cache注解与数据库事务一样,采用的是Spring AOP实现,所以一定要注意,避免使用不当造成注解失效。
总结
Spring Cache 缓存管理器是 Spring 框架中用于管理和维护缓存组件的重要组件。它提供了丰富的缓存实现和配置选项,使得开发者可以轻松地实现缓存功能,从而提高应用的性能和响应速度。
“笑对人生,智慧同行!博客新文出炉,微信订阅号更新更实时,等你笑纳~”