文章目录
- 一,170-缓存-SpringCache-自定义缓存配置
- 二,171-缓存-SpringCache-@CacheEvict
- 1,删除多个缓存
- 2,删除一个缓存
- 三,172-缓存-SpringCache-原理与不足
一,170-缓存-SpringCache-自定义缓存配置
上一节我们提到,@Cacheable的默认行为包括:
- ① key是默认生成的:缓存的名字::SimpleKey::
- ② 缓存的value值,默认使用jdk序列化机制,将序列化的数据存到redis中
- ③ 默认时间是 -1,即永不过期
①可以通过@Cacheable
注解的属性key
自定义。
③可以通过配置文件设置过期时间。
本节将介绍如何修改key、value的序列化机制。
根据SpringBoot的原理,一定有一个类用来封装配置文件中的配置,Spring Cache的这个配置自动装配类是CacheAutoConfiguration
,看这个类的源码,其加载了Redis的配置类RedisCacheConfiguration
,这个类中使用了Spring Cache
的配置创建RedisCacheManger
类,这个类中实现了对Redis的读写操作。
根据源码可以看出,如果容器中有redisCacheConfiguration
对象,就使用容器中的对象,否则就创建一个。
private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration(
CacheProperties cacheProperties,
ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration,
ClassLoader classLoader) {
return redisCacheConfiguration.getIfAvailable(() -> createConfiguration(cacheProperties, classLoader));
}
默认是没有向容器中注入redisCacheConfiguration
对象的,会创建一个,但是创建的对象中没有设置key和value的序列化器,会用默认的JDK序列化器。
所以,我们可以向容器中注入一个redisCacheConfiguration
对象,在这个对象中设置JSON序列化器,在创建RedisCacheManger
对象时,就会使用我们注入的对象,redis就会使用我们配置的json序列化。
所以,我们可以自定义一个配置类,向容器中注入redisCacheConfiguration
对象,在创建这个对象时设置序列化方式。
@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class MyCacheConfig {
// @Autowired
// public CacheProperties cacheProperties;
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// config = config.entryTtl();
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
//将配置文件中所有的配置都生效
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
在这段代码中,创建并向容器中注入了一个RedisCacheConfiguration
对象。
这里需要注意,需要通过@EnableConfigurationProperties
激活CacheProperties
读取和封装配置文件中的配置。
@EnableConfigurationProperties
的作用
- 激活自动绑定:
@EnableConfigurationProperties
注解告诉Spring框架去查找并激活一个或多个由@ConfigurationProperties
标记的类,这些类可以用来绑定配置文件中的属性值。 - 注册绑定类:它会将标记为
@ConfigurationProperties
的类注册为一个配置类,这样就可以直接在Spring容器中注入这些配置类的实例,并且它们会自动绑定到配置文件中的属性。
使用 CacheProperties
的两种方式
-
自动注入 (
@Autowired
):- 作用:使用
@Autowired
注入CacheProperties
类的实例,这种方式可以直接在类的字段上使用,不需要额外的方法调用。 - 示例:
@Autowired private CacheProperties cacheProperties;
- 作用:使用
-
作为方法参数:
- 作用:将
CacheProperties
作为方法参数传递,这种方式通常用于方法内部需要使用配置属性的情况。 - 示例:
@Bean public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) { // ... }
- 作用:将
二,171-缓存-SpringCache-@CacheEvict
Redis缓存保证最终一致性的失效模式,是在更新数据后将缓存中的数据删除,删除缓存数据可以通过@CacheEvict完成,结合@Caching可以删除多个缓存。
1,删除多个缓存
@Caching( evict = {
@CacheEvict(value = {"category"}, key = "'getLevel1Categorys'"),
@CacheEvict(value = {"category"}, key = "'catelogJson'")
}
)
2,删除一个缓存
@CacheEvict(value = {"category"}, key = "'getLevel1Categorys'")
三,172-缓存-SpringCache-原理与不足
对Redis缓存的三个问题:
- 缓存穿透
- 缓存击穿
- 缓存雪崩
SpringCache提供相应的解决方案:
- 针对缓存穿透,可以设置控制缓存
Spring.cache.redis.cache-null-values=true
- 针对缓存雪崩,可以设置不同的过期时间来防止雪崩
- 针对缓存击穿,Spring Cache提供了get方法的本地锁方案,没有分布式锁方案
所以,如果实时性要求高、数据一致性要求高,就不能使用Spring Cache,必须自己编写缓存相关的逻辑来实现分布式锁的方案。