1.引入依赖
本次springboot的版本为2.2.6
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--cache-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--reids-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.查看自动配置类看他给我们配置了什么
spring:
redis:
port: 6379
host: 192.168.83.132
cache:
redis:
time-to-live: 3600000 #毫秒,在redis中存在的时间
key-prefix: cacheKey_ #前缀 若配置则会使用他为前缀,若不配置则会使用我们自己命名的作为前缀
use-key-prefix: false #若为true则会使用前缀,若为false则不会使用前缀
cache-null-values: true #为true则允许存空值
type: redis #使用redis做为缓存
在这里插入图片描述
我们看到CacheConfigurations中对应那个枚举的就是RedisCacheConfiguration这个自动配置类
打开RedisCacheConfiguration自动配置类
点开他
看他的返回值点开getIfAvailable方法
我们再看这个方法getIfAvailable
这是我们才知道原来是先从容器中获取,如果容器中没有用则用这个默认的RedisCacheConfiguration
看他默认给我们配置了什么
分析到这里
若想使用他则需要有上面的
1.引入依赖
2.写配置
3.开启缓存 在启动类或者配置类上标注
@EnableCaching //使用缓存
4.在服务层标志@Cacheable
@Cacheable(value = "键前缀(区域名)",key = "#root.methodName(后缀,我用的方法名)")
他的作用是,先从缓存中查若有则直接返回结果,不需要反射调用我们的业务逻辑,若没有则反射调用我们的业务逻辑并且存入缓存中在将我们业务处理的结果返回。
其实这样就有一个问题
在高并发的时候,100万用户全部去访问,但是没有缓存数据,所以都跑去访问数据库,这样数据库就蹦了(缓存击穿)
其实@Cacheable还有一个属性就是sync
@Cacheable(value = "键前缀(区域名)",key = "#root.methodName",sync = true)
他默认为false当设为true他就会调用
RedisCache中的
这个方法,这个方法加了同步锁
若果不加的话他会调用
没有同步
但这其实也有文问题的,因为我们买一个请求过来都要抢锁,不管有没有缓存都要抢锁,这就很浪费资源,我们拿数据书说话
1.加sync
2.不加sync
几大注解的使用方式
//1. 删除category这个分组下的所有缓存(当以下方法执行时)
//@CacheEvict(value = "categorys",allEntries = true)
@CacheEvict(value = "categorys",allEntries = true)
//清空具体的某一个(失效模式)
@CacheEvict(value = "categorys",key = "'getLevelOneCategory'"),
//2.多个操作可以放在Caching中
@Caching(evict = {
@CacheEvict(value = "categorys",key = "'getLevelOneCategory'"),
@CacheEvict(value = "categorys",key = "'getCatalogJson'")
})
@Transactional
@Override
public void saveDetail(CategoryEntity category) {
this.baseMapper.updateById(category);
String name = category.getName();
if(!StringUtils.isEmpty(name)){
categoryBrandRelationDao.updateDetail(category.getCatId(),category.getName());
}
}
//这个用在修改或删除插入的操作上且这个操作有返回值,他会把这个返回值存在redis中(双写模式)
@CachePut(value = "categorys",key = "'getLevelOneCategory'")
//在cacheManage中的分组为categorys 在redis中的键为categorys::getLevelOneCategory
@Cacheable(value = {"categorys"},key = "#root.method.name")
@Override
public List<CategoryEntity> getLevelOneCategory() {
List<CategoryEntity> parent_cid = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
System.out.println("查询数据库");
return parent_cid;
}