《苍穹外卖》项目学习记录-Day7缓存菜品

ops/2025/2/5 13:07:17/

我们优先去读取缓存数据,如果有就直接使用,如果没有再去查询数据库,查出来之后再放到缓存里去。

微信小程序根据分类来展示菜品,所以每一个分类下边的菜品对应的就是一份缓存数据,这样的话当我们使用这个数据的时候,就可以一次性的把这个分类下面的缓存数据给它加载出来。Redis保存数据是key-value结构,我们可以使用分类的id来作为我们缓存的key,而value则是分类下面这些具体的菜品数据,这些菜品数据可以使用String字符串来进行保存。Redis当中的数据类型跟Java当中的数据类型并不是完全对应的,也就是说Java当中任何一个对象,都可以给它转成Redis当中的String字符串来进行存储。从Java对象这个角度来考虑,这些一个分类下面的具体菜品数据可以用List集合进行存储,然后把这个集合进行序列化,最终转成Redis的一个字符串来存储。

数据库中菜品数据有变更时清理缓存数据,如果不清理会造成我们这个数据的不一致,比如说在商家管理端把某一个菜品的价格改了,如果不清理对应的缓存,因为管理端改了菜品价格修改的是MySQL数据库里面数据,但是小程序展示出来的是读取缓存Redis里面的数据,Redis里面的数据没有改,所以小程序里面展示的还是原来的价格。

1.查询redis中是否存在菜品数据。放进去是什么类型的取出来就是什么类型的,放进去是List<DishVo>类型的所以取出来要强转成List<DishVo>类型的。

2.如果存在,直接返回,无须查询数据库。

3.如果不存在,查询数据库,将查询到的数据放入redis中。

数据缓存到了Redis里

使用Redis缓存数据要保证数据的一致性,这个数据的一致性主要是体现在我们MySQL数据库当中的数据跟Redis缓存当中的数据必须是一致的,也就是说当我们MySQL数据库当中的数据发生变更时,我们需要及时的把Redis缓存的数据清理掉,然后它重新去查MySQL数据库,这样的话就一致了。

新增菜品我们可以精确的去清理掉分类id对应的缓存数据。

菜品批量删除有可能会删除多个菜品,而多个菜品可能属于某一个分类下边,也可能是某些不同分类下边的菜品,也就是它可能会影响到多个key,影响到哪个key,需要查询MySQL数据库才会知道。这样太复杂,所以如果执行了菜品批量删除,我们就把所有的缓存数据清理掉,也就是dish_开头的数据都给它清理掉。删除的时候不能识别通配符,所以我们先把所有的key查询出来,然后再去删除。

修改菜品如果是修改了分类,那就影响到了两份缓存数据,也就是原先的分类会少一个,修改后的分类会多一个,如果修改的是菜品名称,价格这些属性则只会影响一份缓存数据。这样看来修改菜品有可能会影响一份缓存数据,有可能会影响两份缓存数据,修改操作并不是常规操作,一般很少去修改,所以我们这里简单的处理了,统一清理掉所有的缓存数据

菜品起售停售,需要根据菜品id把对应的数据查出来,菜品数据里面就有分类id,这样就可以动态的把key构造出来,这样就可以清理某一个key,也就是菜品起售停售对应的缓存数据,这样去实现还要额外去查询数据,所以这里我们统一清理所有的缓存数据。

package com.sky.controller.admin;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Set;/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 新增菜品* @param dishDTO* @return*/@PostMapping@ApiOperation("新增菜品")public Result save(@RequestBody DishDTO dishDTO) {log.info("新增菜品:{}", dishDTO);dishService.saveWithFlavor(dishDTO);//清理缓存数据String key = "dish_" + dishDTO.getCategoryId();cleanCache(key);return Result.success();}/*** 菜品分页查询** @return*/@GetMapping("/page")@ApiOperation("菜品分页查询")public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {log.info("菜品分页查询:{}", dishPageQueryDTO);PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);return Result.success(pageResult);}/*** 菜品批量删除* @param ids* @return*/@DeleteMapping@ApiOperation("菜品批量删除")public Result delete (@RequestParam List<Long> ids){log.info("菜品批量删除,{}",ids);dishService.deleteBatch(ids);//将所有的菜品缓存数据清理掉,所有以dish_开头cleanCache("dish_*");return Result.success();}/*** 根据id查询菜品和对应的口味数据* @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品")public Result<DishVO> getById(@PathVariable Long id){log.info("根据id查询菜品:{}",id);DishVO dishVO = dishService.getByIdWithFlavor(id);return Result.success(dishVO);}/*** 修改菜品* @param dishDTO* @return*/@PutMapping@ApiOperation("修改菜品")public Result update(@RequestBody DishDTO dishDTO){log.info("修改菜品:{}",dishDTO);dishService.updateWithFlavor(dishDTO);//将所有的菜品缓存数据清理掉,所有以dish_开头cleanCache("dish_*");return Result.success();}/*** 菜品的起售停售* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("菜品的起售停售")public Result<String> startOrStop(@PathVariable Integer status,Long id){log.info("菜品的起售停售:{},{}",status == 1 ? "起售" : "停售",id);dishService.startOrStop(status,id);//将所有的菜品缓存数据清理掉,所有以dish_开头的keycleanCache("dish_*");return Result.success();}/*** 根据分类id查询菜品** @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<Dish>> list(Long categoryId) {List<Dish> list = dishService.list(categoryId);return Result.success(list);}/*** 清理缓存数据* @param patten*/private void cleanCache(String patten){Set keys = redisTemplate.keys(patten);redisTemplate.delete(keys);}
}

·测试

 

我们停售之后也把相应的缓存数据清理掉,然后重新查询数据库,它就变成这个样子了。

 


http://www.ppmy.cn/ops/155873.html

相关文章

RESTful API的设计原则与这些原则在Java中的应用

RESTful API 是基于 REST&#xff08;Representational State Transfer&#xff09; 架构风格设计的 API&#xff0c;其核心目标是提高系统的可伸缩性、简洁性和可维护性。以下是 RESTful API 的设计原则及在 Java 中的实现方法&#xff1a; 一、RESTful API 的核心设计原则 客…

98,【6】 buuctf web [ISITDTU 2019]EasyPHP

进入靶场 代码 <?php // 高亮显示当前 PHP 文件的源代码&#xff0c;通常用于调试或展示代码&#xff0c;方便用户查看代码逻辑 highlight_file(__FILE__);// 从 GET 请求中获取名为 _ 的参数值&#xff0c;并赋值给变量 $_ // 符号用于抑制可能出现的错误信息&#xff…

全栈开发:使用.NET Core WebAPI构建前后端分离的核心技巧(一)

目录 cors解决跨域 依赖注入使用 分层服务注册 缓存方法使用 内存缓存使用 缓存过期清理 缓存存在问题 分布式的缓存 cors解决跨域 前后端分离已经成为一种越来越流行的架构模式&#xff0c;由于跨域资源共享(cors)是浏览器的一种安全机制&#xff0c;它会阻止前端应用…

kubernetes-部署性能监控平台

在当今快速发展的云计算时代&#xff0c;Kubernetes 已成为容器编排的事实标准。随着越来越多的应用迁移到 Kubernetes 平台上&#xff0c;如何有效地监控集群的健康状态、资源使用情况以及应用性能变得尤为重要。一个完善的监控系统可以帮助我们及时发现问题、优化资源配置&am…

02.01、移除重复节点

02.01、[简单] 移除重复节点 1、题目描述 编写代码&#xff0c;移除未排序链表中的重复节点。保留最开始出现的节点。 2、解题思路 为了实现这一目标&#xff0c;我们可以使用一个哈希表&#xff08;或集合&#xff09;来记录已经遇到的节点值&#xff0c;逐步遍历链表并删…

每日一题——滑动窗口的最大值

滑动窗口的最大值 题目描述示例说明 解题思路双端队列的特点实现步骤代码实现&#xff08;C语言&#xff09;代码解析 总结 题目描述 给定一个长度为 n 的数组 num 和滑动窗口的大小 size&#xff0c;找出所有滑动窗口里数值的最大值。 例如&#xff0c;如果输入数组 {2, 3, …

mac 手工安装OpenSSL 3.4.0

如果你希望继续安装 openssl-3.4.0 而不是降级到 3.1.1&#xff0c;可以尝试以下解决方案。根据你提供的错误信息&#xff0c;问题可能出在测试阶段&#xff08;make test&#xff09;&#xff0c;我们可以尝试跳过测试或修复测试失败的原因。 --- ### **解决方案&#xff1a…

IFeatureWorkspace.CreateFeatureClass(),报错对COM组件的调用返回了错误 HRESULT E_FAIL

1、问题描述&#xff1a;在AE开发中&#xff0c;新增一个空的shpfile文件的时候&#xff0c;报错&#xff0c;如下图&#xff1a; 2、原因分析&#xff1a;产生此问题的原因是未设置默认字段的默认参数&#xff0c;特别是未设置IGeometryDef 参数。 3、解决方案&#xff1a;在…