④. @CacheEvict、@Caching、@CachePut的使用
- ①. @CacheEvict:触发将数据从缓存删除的操作(相当于失效模式)
- ②. @Caching:组合以上多个操作
- ③. @CachePut:不影响方法执行更新缓存(双写模式) 需要有返回值
/** * 存储同一个类型的数据,都可以指定成同一个分区。分区名默认就是缓存的前缀 * (我们需要在配置文件中将前缀的使用关闭) * @param category */ //@CacheEvict(value = "category",key = "'getLevel1Category'") // @Caching(evict = { // @CacheEvict(value = "category",key = "'getLevel1Category'"), // @CacheEvict(value = "category",key = "'getCatalogJson'") // }) //删除category分区中所有的数据 //@CacheEvict(value = "category",allEntries = true)//失效模式 @Transactional @Override public void updateCasCade(CategoryEntity category) { this.updateById(category); categoryBrandRelationService.updateCategory(category.getCatId(),category.getName()); }
//application.properties spring.cache.type=redis #spring.cache.cache-names= #设置存活时间,ms为单位 spring.cache.redis.time-to-live=3600000 #如果指定了前缀,就使用我们指定的前缀,如果没有就默认使用缓存的名字作为前缀 #CACHE_getLevel1Category #spring.cache.redis.key-prefix=CACHE_ #默认是使用前缀的 #如果开始了这个,那么缓存的key=getLevel1Category,没有CACHE #spring.cache.redis.use-key-prefix=false #是否缓存空值,防止缓存穿透 spring.cache.redis.cache-null-values=true
⑤. SpringCache原理与不足
- ①. 读模式
缓存穿透:查询一个null数据。解决方案:缓存空数据,可通过spring.cache.redis.cache-null-values=true
缓存击穿:大量并发进来同时查询一个正好过期的数据。解决方案:加锁 ? 默认是无加锁的;
使用sync = true来解决击穿问题
缓存雪崩:大量的key同时过期。解决:加随机时间。
// 解决缓存击穿加锁 @Cacheable(value={"category"},key = "#root.method.name",sync = true)
- ②. 写模式(缓存与数据库一致)
- 读写加锁。
- 引入Canal,感知到MySQL的更新去更新Redis
- 读多写多,直接去数据库查询就行
- ③. 总结
- 常规数据(读多写少,即时性,一致性要求不高的数据,完全可以使用Spring-Cache):
- 写模式(只要缓存的数据有过期时间就足够了)