167、缓存-SpringCache-简介-172、缓存-SpringCache-原理与不足
感觉也比较简单,视频中也是跟着官网的介绍做的,可以参考前面一篇的中文翻译。
主要代码如下:
/** * 级联更新所有关联的数据 * @param category */ @Transactional @Override // @Caching( evict ={ // @CacheEvict(value={"category"},key = "‘getLevel1Categorys‘"), // @CacheEvict(value={"category"},key = "‘getCatalogJson‘‘") // }) @CacheEvict(value ="category",allEntries = true) public void updateCascade(CategoryEntity category) { this.updateById(category); categoryBrandRelationService.updateCategory(category.getCatId(),category.getName()); } /** * 查询所有一级分类 * * @return */ // @Cacheable(value={"category"},key = "‘level1Categorys‘") //代表当前结果需要缓存,如果有就不需要缓存,没有则缓存 @Cacheable(value={"category"},key = "#root.method.name") @Override public List<CategoryEntity> getLevel1Categorys() { List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0)); return categoryEntities; } public Boolean lock(String key, String value,String luaPath) throws IOException { DefaultRedisScript<Boolean> lockScript = new DefaultRedisScript<>(); ClassPathResource resource = new ClassPathResource(luaPath); ResourceScriptSource source = new ResourceScriptSource(resource); lockScript.setScriptSource(source); lockScript.setResultType(Boolean.class); Boolean result = (Boolean) stringRedisTemplate.execute(lockScript, Arrays.asList(key, value)); return result; } @Override @Cacheable(value={"category"},key = "#root.method.name") public Map<String, List<Catalog2Vo>> getCatalogJson() { //查询出所有分类 List<CategoryEntity> selectList = baseMapper.selectList(null); //先查出所有一级分类 List<CategoryEntity> level1Categorys = getCategorys(selectList, 0L); //封装数据 map k,v 结构 Map<String, List<Catalog2Vo>> map = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> { //每一个的一级分类,查到这个一级分类的二级分类 List<CategoryEntity> category2Entities = getCategorys(selectList, v.getCatId()); List<Catalog2Vo> catelog2Vos = null; if (category2Entities != null) { catelog2Vos = category2Entities.stream().map(level2 -> { //封装catalog2Vo Catalog2Vo catalog2Vo = new Catalog2Vo(v.getCatId().toString(), null, level2.getCatId().toString(), level2.getName()); //每一个二级分类,查到三级分类 List<CategoryEntity> category3Entities = getCategorys(selectList, level2.getCatId()); if (category3Entities != null) { List<Object> catalog3List = category3Entities.stream().map(level3 -> { //封装catalog3Vo Catalog2Vo.Catalog3Vo catalog3Vo = new Catalog2Vo.Catalog3Vo(level2.getCatId().toString(), level3.getCatId().toString(), level3.getName()); return catalog3Vo; }).collect(Collectors.toList()); //封装catalog3Vo到catalog2Vo catalog2Vo.setCatalog3List(catalog3List); } return catalog2Vo; }).collect(Collectors.toList()); } //返回v=catalog2Vo return catelog2Vos; })); return map; }
演示的结果图:
修改数据,缓存消失:
在刷新首页,缓存修改后的数据
总结如下:
/** * Spirng-Cache的不足 * 1)读模式: * 缓存穿透:查询一个null数据。解决:缓存空数据:cache-null-values=true * 缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加锁,默认无锁,sync=true * 缓存雪崩:大量的key同时过期。解决:加随机时间。加上过期时间 spring.cache.redis.time-to-live=3600000 * 2)写模式:(缓存与数据库一致) * 1:写入加锁 * 2:引入canal,感受到mysql的变化 * 3:读多写多,直接去数据库查询就行 * 总结: * 常规数据(读多写少,即时性,一致性要求不高的数据,完全可以使用spring-cache) * 特殊数据:特殊设计 */ //@MapperScan("com.dalianpai.gulimall.product.dao") @ComponentScan("com.dalianpai") @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients("com.dalianpai.gulimall.product.feign") public class GulimallProductApplication { public static void main(String[] args) { SpringApplication.run(GulimallProductApplication.class, args); } }
原文:https://www.cnblogs.com/dalianpai/p/13205307.html