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

devtools/2025/2/4 3:41:01/

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

微信小程序根据分类来展示菜品,所以每一个分类下边的菜品对应的就是一份缓存数据,这样的话当我们使用这个数据的时候,就可以一次性的把这个分类下面的缓存数据给它加载出来。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/devtools/155893.html

相关文章

深度学习:基于MindNLP的RAG应用开发

什么是RAG&#xff1f; RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09; 是一种结合检索&#xff08;Retrieval&#xff09;和生成&#xff08;Generation&#xff09;的技术&#xff0c;旨在提升大语言模型&#xff08;LLM&#xff09;生…

Maven全解析:第二个项目 IDEA 整合 Maven

创建Maven 项目目录(注意以下所有引用包路径&#xff0c;设置成自己的包路径)&#xff1a; src/main/java ----存放项目的 .java 文件、 src/main/resoutces ---存放项目资源文件&#xff0c;如 Spring&#xff0c;MyBatis 配置文件 src/test/java ---存放所有测试 .java…

每日一博 - 三高系统架构设计:高性能、高并发、高可用性解析

文章目录 引言一、高性能篇1.1 高性能的核心意义 1.2 影响系统性能的因素1.3 高性能优化方法论1.3.1 读优化&#xff1a;缓存与数据库的结合1.3.2 写优化&#xff1a;异步化处理 1.4 高性能优化实践1.4.1 本地缓存 vs 分布式缓存1.4.2 数据库优化 二、高并发篇2.1 高并发的核心…

leetcode27.删除有序数组中的重复项

目录 问题描述判题标准示例提示 具体思路思路一思路二 代码实现 问题描述 给你一个非严格递增排列的数组nums&#xff0c;请你原地删除重复出现的元素&#xff0c;使每个元素只出现一次&#xff0c;返回删除后数组的新长度。元素的相对顺序应该保持一致 。然后返回nums中唯一元…

关于DNN检测中替换caff用Tensorflow的注意事项

首先确保计算机中有python标准库&#xff0c;之后在环境变量中加入python的路径&#xff0c;这样在管理员的cmd中才不会出现tf_text_graph_ssd.py无法编译的情况&#xff0c;之后要在python的环境下添加opencv&#xff0c;不然会导致无法生成pbtxt文件&#xff0c;从而std::str…

机器学习算法在网络安全中的实践

机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践&#xff0c;包括基本概念、常见算法及其应用案例&#xff0c;从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题&#xff0c;随着互联…

JavaScript系列(54)--性能优化技术详解

JavaScript性能优化技术详解 ⚡ 今天&#xff0c;让我们继续深入研究JavaScript的性能优化技术。掌握这些技术对于构建高性能的JavaScript应用至关重要。 性能优化基础概念 &#x1f3af; &#x1f4a1; 小知识&#xff1a;JavaScript性能优化涉及多个方面&#xff0c;包括代…

【云安全】云原生-K8S-简介

K8S简介 Kubernetes&#xff08;简称K8S&#xff09;是一种开源的容器编排平台&#xff0c;用于管理容器化应用的部署、扩展和运维。它由Google于2014年开源并交给CNCF&#xff08;Cloud Native Computing Foundation&#xff09;维护。K8S通过提供自动化、灵活的功能&#xf…