目录
缓存-SpringCache-整合&体验@Cacheable
缓存-SpringCache-@Cacheable的细节设置
缓存-SpringCache-简介
缓存的编写逻辑:查询缓存,缓存命中从缓存中获取;缓存未命中则从数据库中查询并存入缓存。
对于数据一致性问题可以采用:①双写模式 ②失效模式
对于双写模式或失效模式存在的问题:加锁
每次对业务进行缓存的编写会比较繁琐,Sring对于缓存的使用进行了一个封装即Spring Cache组件。
Spring Cache的文档地址:Integration
CacheManager实际上就是定义了Cache的各种规则,Cache才是我们对缓存数据的CRUD操作
常用的缓存注解:
@Cacheable:触发将数据存储到缓存的操作
@CacheEvic:触发将数据从缓存中删除的操作
@CachePut:不影响方法执行更新缓存
@Caching:组合以上多个操作
@CacheConfig:在类级别共享缓存的相同配置
缓存-SpringCache-整合&体验@Cacheable
整合Spring Cache开发的步骤:
①导入cache、redis依赖
<!--导入Spring Cache的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--导入SpringBoot整合Redis的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
②配置
1.配置类型
cache的所有xml配置都在CacheProperties.class中
2.自动配置
由下图可知,通过CacheType自动映射Cache配置类。因此,我们配置Cache的类型为Redis,Spring Cache将自动配置RedisAutoConfiguration、RedisCacheManager
3.配置redis作为缓存,redis的配置
spring.cache.type=REDIS
③测试使用缓存
1.开启缓存功能:@EnableCache
2.只需要使用注解就能完成缓存操作
@Cacheable的作用:代表当前方法的结果需要缓存,如果缓存中有则方法不调用,若缓存中没有则调用方法并将结果保存至缓存中
"category":代表缓存分区名称,为需要缓存的数据指定存储的缓存分区。一般按业务进行分区。
查看结果: 访问localhost:10000,从数据库查询一级类目只打印了一次,说明缓存生效了
缓存-SpringCache-@Cacheable的细节设置
使用@Cacheable默认行为:
①默认生成key ②缓存的value,默认使用jdk序列化机制。将序列化后的数据存储到redis中。 ③默认过期的时间为: -1 即永不过期
@Cacheable自定义配置:
①指定生成的缓存使用的key
1.自定义key的名称,使用''否则默认为表达式
2.使用SpEL指定key
具体细节可以参考文档的Available Caching SpEL Evaluation Context
②自定义过期时间,单位:毫秒
③将数据保存为json格式
将在下一章节讲述
缓存-SpringCache-自定义缓存配置
原理:CacheAutoConfiguration -> 自动配置RedisCacheConfiguration -> 自动配置RedisCacheManager -> 初始化所有缓存 -> 每个缓存决定使用什么配置 -> 如果redisCacheConfiguration有就用已有的,没有就用默认配置 -> 想修改缓存的配置,只需要给容器中放一个RedisCacheConfiguration 配置即可 -> 就会应用到当前RedisCacheManager管理的所有缓存分区中
自定义RedisCacheConfiguration 步骤:
①编写配置类
②创建一个默认配置,再进行重新配置
③配置配置文件项
1.使用EnableConfigurationProperties注解将CacheProperties注入容器中
2. 导入CacheProperties的Bean
3. 配置配置文件项
@EnableConfigurationProperties({CacheProperties.class})
@Configuration
@EnableCaching
public class MyRedisCacheConfig {
@Autowired
private CacheProperties cacheProperties;
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
// 调用 RedisCacheConfiguration 的 defaultCacheConfig 静态方法生成一个默认配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// key 实现 String 序列化
config=config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
// value 实现 jason格式
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.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
常用配置说明:
①spring.cache.redis.key-prefix :用于指定key的前缀,若开启则使用自定义前缀,若不开启则使用缓存分区名作为前缀。
②spring.cache.redis.use-key-prefix: 默认为true,设置为false的话则不使用自定义前缀也不使用缓存分区名作为前缀
③spring.cache.redis.cache-null-values: 默认为true,允许存储null,防止缓存穿透
缓存-SpringCache-@CacheEvict
约定前缀使用缓存名
使用@CacheEvict删除多个缓存数据
方法一:
方法二:将缓存分区category中的所有缓存清空
缓存-SpringCache-原理与不足
Spring-Cache 的不足:
①读模式:
1.缓存穿透问题:查询一个null数据 ; 解决方案: 保存一个null数据 ;通过配置:spring.cache.redis.cache-null-values=true
2.缓存击穿问题:查询一个刚好过期的数据;解决方案: spring-cache 默认CRUD方法不加synchronized,通过使用 sync = true 解决,会调用加了本地锁synchronized的get()方法
3.缓存雪崩问题:同一时间大量数据过期; 解决方案:配置过期时间,spring.cache.redis.time-to-live; 添加随机时间容器弄巧成拙
②写模式:(数据一致性问题)
1.读写加锁
2.引入Cannal,监控Mysql的更新去更新缓存
3.读多写多,直接去数据库查询即可
总结:
1.常规数据(读多写少,一致性、及时性要求不高的数据),使用Spring-Cache完全够用
2.特殊数据,特殊设计