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

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



一、代码实现缓存

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();
    }
相关推荐
全栈弄潮儿²⁰²⁴2 天前
AI Agent 开发实战(30):限流、缓存与成本控制
人工智能·gpt·缓存·agent·限流·agi·成本控制
Together_CZ2 天前
DeepSeek-V4.1-Flash:Pushing the Limits of KV Cache Compression——推动 KV 缓存压缩的极限
缓存·llm·compression·kv cache·deepseek·v4.1-flash·推动 kv 缓存压缩的极限
Pioneer000013 天前
我用 Redis + 网关做多模型 API 路由:缓存命中率 95%+ 的工程实践
人工智能·redis·后端·缓存·性能优化·架构
hweiyu003 天前
Redis命令:MSETNX
redis·缓存
wdfk_prog3 天前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
是Dream呀4 天前
Harness 工程:让 Agent 真正把任务做完
人工智能·分布式·缓存·agent
努力努力再努力wz4 天前
【Redis进阶系列】:从主从复制到 Sentinel,一文建立故障检测、Leader 选举与 Failover 的完整心智模型
数据库·redis·缓存
wdfk_prog4 天前
ROS教程10:从 gtest 到 rostest——Unit Test、Node 集成测试、rosbag 与 rqt 验证闭环
运维·缓存·docker·容器·ros
程序猿乐锅5 天前
【黑马点评 | 第四篇】Redis缓存雪崩
java·数据库·spring boot·redis·缓存
HanhahnaH5 天前
Redis单线程和Tair多线程架构设计对比
分布式·缓存