首先我们讲一下为什么要使用缓存?
通过空间换时间,加快速率,
什么时间使用缓存?
在数据库中不经常改变的。但是经常查询的进行缓存,例如:页面分类
为什么不使用本地缓存,本地缓存就相当于,如果缓存没有就封装在map(举例)中,本地进行缓存,这样的话,只可以在本项目中缓存,不可以进行清除,再一个就是不持久化。。。
这样使用到了分布式缓存,常用的分布式缓存有redis,mongodb
这里我们使用Redis
Redis可以搭建集群,主要有两种方式:哨兵和主从;
privateArrayList<CourseType>getCourseTypes() {
List<CourseType>allCourseTypes=selectList(null);
Map<Long, CourseType>collect=allCourseTypes.stream().collect(Collectors.toMap(CourseType::getId, t->t));
ArrayList<CourseType>resultList=newArrayList<>();
allCourseTypes.forEach(res->{
/*如果没有Pid就直接放入List*/
if (res.getPid()==null||res.getPid().equals(0L)){
resultList.add(res);
}else {
/*如果有Pid就找父类*/
CourseTypecourseType=collect.get(res.getPid());
if (courseType!=null){
courseType.getChildren().add(res);
}
}
});
// hashMap.put(RedisConstants.COURSE_KEY,resultList);
/*把查询到的数据缓存到Redis中*/
redisTemplate.opsForValue().set(RedisConstants.COURSE_KEY,resultList);
returnresultList;
}
/*Redis进行缓存*/
@Override
public List<CourseType> treeData() {
List<CourseType> courseTypes = (List<CourseType>)redisTemplate.opsForValue().get(RedisConstants.COURSE_KEY);
if (courseTypes!=null){
return hashMap.get(RedisConstants.COURSE_KEY);
}else {
return getCourseTypes();
}
}
但是redis‘缓存存在这样存在一个问题(面试强调)
1.修改数据库的同时,修改reids中的数据(重置)会有短暂数据不一致
2.先删除redis中的数据,然后进行修改数据库,在高并发的情况下,可能正在修改数据库中数据的时候,又缓存之前的数据;
3. 延迟双删
先删除redis中的数据,在修改数据库
在修改数据库之后,再去删除redis数据
防止个别人,在我修改数据的时候,进行访问缓存我之前的数据
4.另外解决的一种办法
使用Alibaba的canal组件,它可以做数据库的同步操作。可以监听数据库的binary log日志,可以自动同步mysql或者其他的数据库的数据。
如果小伙伴不想导入新的组件,接下来我给大家手码:
重写三个方法
![](https://img-blog.csdnimg.cn/img_convert/13fe384734facbe19dac236075e00549.png)
@Override
public boolean insert(CourseType entity) {
boolean insert = super.insert(entity);
if (insert){
// /*插入成功之后删除Redis缓存中的数据,或者直接调用查询方法覆盖*/
// redisTemplate.delete(RedisConstants.COURSE_KEY);
getCourseTypes();
}
return insert;
}
@Override
public boolean deleteById(Serializable id) {
boolean b = super.deleteById(id);
if (b){
getCourseTypes();
}
return b;
}
@Override
public boolean updateById(CourseType entity) {
boolean b = super.updateById(entity);
if (b){
getCourseTypes();
}
return b;
}
SpringCache注解缓存
@Cacheable:触发缓存写入。
@CacheEvict:触发缓存清除。
@CachePut:更新缓存(不会影响到方法的运行)。
@Caching:重新组合要应用于方法的多个缓存操作。
@CacheConfig:设置类级别上共享的一些常见缓存设置。
@CacheEvict(cacheNames = RedisConstants.COURSE_KEY,key = "'all'")
@Override
public boolean insert(CourseType entity) {
return super.insert(entity);
}
@Override
@CacheEvict(cacheNames = RedisConstants.COURSE_KEY,key = "'all'")
public boolean deleteById(Serializable id) {
return super.deleteById(id);
}
@Override
@CacheEvict(cacheNames = RedisConstants.COURSE_KEY,key = "'all'")
public boolean updateById(CourseType entity) {
return super.updateById(entity);
}
/*Redis进行缓存*/
@Override
@Cacheable(cacheNames = RedisConstants.COURSE_KEY,key = "'all'")
public List<CourseType> treeData() {
return getCourseTypes();
}