外卖开发(六)—— 高查询量数据的缓存

外卖开发(六)------ 高查询量数据的缓存



一、代码实现缓存

1、查询缓存

在查询的时候,先去redis中查找数据,如果存在则直接返回数据;否则就去数据库进行查找,并将查找结果存入redis中,并返回数据。(redis的key设置为categoryId)

java 复制代码
@GetMapping("list")
    public Result<List<DishVO>> list(Long categoryId){
        //查询redis中是否存在数据 存在则直接去redis 否则去查数据库
        //构造key
        String key = "dish_" + categoryId;
        
        //查询redis中是否存在数据
        List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
        if (list !=null && list.size()>0){
            return Result.success(list);
        }
        
        //如果不存在,只能去数据库查找
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE); //查询起售中的商品
        List<DishVO> listVO =  dishService.listWithFlavor(dish);
        
        //将数据放入redis
        redisTemplate.opsForValue().set(key,listVO);
        return Result.success(listVO);
    }

2、修改数据时删除缓存

如果数据库中数据更新,如删除、修改、增加等,需要对redis缓存进行删除,保持数据一致性。(redis的key设置为categoryId)

新增菜品中,只需对相应的数据进行删除。

java 复制代码
 /**
     * 新增菜品
     * @param dishDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增菜品")
    public Result addDish(@RequestBody DishDTO dishDTO){
        log.info("新增菜品:{}",dishDTO);
        dishService.insertDish(dishDTO);
        //清理缓存
        String key = "dish_" + dishDTO.getCategoryId();
        redisTemplate.delete(key);

        return Result.success();
    }

删除菜品、修改菜品涉及到复杂的数据库操作,为简化redis操作,直接删除所有redis缓存

java 复制代码
/**
     * 批量删除菜品
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("批量删除菜品")
    public Result deleteDish(@RequestParam List<Long> ids){
        dishService.deleteDish(ids);
        
        //删除全部redis缓存
        Set keys = redisTemplate.keys("dish_*");  //获取redis中所有的key------通配符dish_*获取,并删除全部
        redisTemplate.delete(keys);
        
        return Result.success();
    }

二、spring cache注解实现

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache提供了一层抽象,底层可以切换不同的缓存实现,例如:

EHCache
Caffeine
Redis

xml 复制代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.7.3</version>
</dependency>


1、Cacaheable

@Cacheable(cacheNames = "setmealCache",key = "#categoryId")
@Cacheable(cacheNames = "setmealCache",key = "#setmeal.id") //如果形参是实体类对象,可以用 ". " 来获取属性值

@Cacheable中有两个参数,第一个是cacheNames,指定了redis数据库中的key值的前半部分(通用标识),第二个是唯一标识,可以动态指定方法形参中的属性值,比如将唯一的id作为Redis的key值的的后半部分,这样就可以唯一的标识为一个redis。

总结来说,@Cacheable 中指定的参数,可以表示为:"setmealCache::#categoryId",其中每一个冒号都代表一层,有两个冒号,且冒号中间没有东西,则表示为Empty。如下图所示

java 复制代码
	/**
     * 根据分类id查询套餐
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询套餐")
    @Cacheable(cacheNames = "setmealCache",key = "#categoryId")
    public Result<List<Setmeal>> list(Long categoryId){    
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);
        List<Setmeal> list = setmealService.getByCategoryId(setmeal);
      
        return Result.success(list);
    }

2、CacheEvict

@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId") 删除指定的cache,cacheName和key一起指定Redis的key
@CacheEvict(cacheNames = "setmealCache",allEntries = true) 删除cacheName下所有的cache,allEntires = true 指定为删除所有

java 复制代码
/**
     * 新增套餐
     * @param setmealDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增套餐")
    @CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
    public Result insertSetmeal(@RequestBody SetmealDTO setmealDTO){
        setmealService.addSetmeal(setmealDTO);
        
        return Result.success();
    }
java 复制代码
/**
     * 修改套餐
     * @param setmealDTO
     * @return
     */
    @PutMapping
    @ApiOperation("修改套餐")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result update(@RequestBody SetmealDTO setmealDTO){
        setmealService.update(setmealDTO);

        return Result.success();
    }
相关推荐
真上帝的左手4 小时前
30. 技术专题-‌应用框架组件-缓存-Redis
数据库·redis·分布式·缓存·中间件
bksczm5 小时前
C++Redis开发(Ubuntu 22.04)
数据库·redis·缓存
goehou5 小时前
缓存该删还是该改,LLM 服务里的双写问题
redis·缓存·llm·一致性·系统设计
利威尔xu17 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
程序猿编码1 天前
解决 LLM 算力浪费,一套统一 KV 管理层实现缓存复用
人工智能·神经网络·机器学习·缓存·llm·大模型推理
zrc0070071 天前
steam无法登录 steam错误 登录时出现错误。请稍后再试。解决办法 steam无法登录解决办法 湖南地区steam DNS问题解决办法
windows·经验分享·游戏·缓存·游戏程序·创业创新·玩游戏
CCblandy1 天前
缓存淘汰实测:一次全表扫描把 LRU 命中率从 46% 打到 38%,W-TinyLFU 守住 50% 却贵 11 倍
后端·python·缓存·性能优化·架构
Wang's Blog1 天前
Java 项目实战: 交友项目 - 小视频模块实战:访客记录、FastDFS 存储与 SpringCache 缓存
java·缓存·交友
麻瓜code1 天前
双写一致性:为什么是“删缓存“,而不是“改缓存“
java·缓存·mybatis
snow@li1 天前
redis:RedisDesktopManager(RDM/RESP.app)Redis 数据可视化全景深度梳理
数据库·redis·缓存