首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【项目日志|苍穹外卖】Day7: Redis缓存优化

【项目日志|苍穹外卖】Day7: Redis缓存优化

作者头像
超级苦力怕
发布2025-12-23 17:58:00
发布2025-12-23 17:58:00
70
举报

本文记录了苍穹外卖项目第七天的学习内容,重点介绍了Redis缓存技术的应用、Spring Cache框架的使用,通过缓存优化显著提升系统性能。

请添加图片描述
请添加图片描述


今日完成任务

  • 缓存菜品功能
  • 缓存套餐功能
  • 添加购物车接口
  • 查看购物车接口
  • 清空购物车接口
  • 删除购物车商品接口

主要功能展示

实现缓存套餐功能
Spring Cache的使用

Spring Cache 是 Spring 提供的一个缓存抽象框架,旨在简化在 Java 应用中集成和使用缓存的流程, 从而提升系统性能、减少数据库或远程服务的访问压力。

业务场景 由于在用户使用高峰的时候,会短时间有大量的并发请求。再直接从数据库中查找数据就不合适了,这是个 I/O 操作,再高峰期会使得用户端卡顿,造成体验下降。

请添加图片描述
请添加图片描述

解决思路 因此,我们需要通过 Redis 数据库建立缓存区,从而再查询菜品时,若缓存区中有数据,则直接获取,若缓存区中无该数据,再去查找数据库, 从而达到优化查询效率的方法。

Spring 提供了相应框架 Spring Cache,从而通过注解解决。

实现流程 利用@CacheEvict注解,直接清理相应的数据, 这里会在拓充知识点 Spring Cache 中详解

在这里插入图片描述
在这里插入图片描述

拓充知识点

1.Spring Cache 注解详解

核心注解功能表

注解

功能描述

使用场景

关键参数

@EnableCaching

开启缓存注解

配置类

@Cacheable

赋予缓存功能

查询操作

cacheNames, key

@CachePut

更新缓存数据

更新操作

cacheNames, key

@CacheEvict

清除缓存数据

删除操作

cacheNames, key, allEntries

详细注解说明 @EnableCaching - 缓存开关

代码语言:javascript
复制
@Configuration
@EnableCaching
public class CacheConfig {
    // 缓存配置
}
在这里插入图片描述
在这里插入图片描述

@Cacheable - 缓存查询

代码语言:javascript
复制
@Cacheable(cacheNames = "dishCache", key = "#categoryId")
public List<DishVO> list(Long categoryId) {
    // 查询逻辑
}
在这里插入图片描述
在这里插入图片描述

参数说明:

cacheNames:指定缓存名称,对应缓存管理器中的缓存名 key:指定缓存的键,可通过SpEL表达式指定

注意:该注解可标记在方法或类上

@CachePut - 缓存更新

代码语言:javascript
复制
@CachePut(cacheNames = "myCache", key = "#param")
public Object myMethod(String param) {
    // 方法体
}

@CacheEvict - 缓存清除

代码语言:javascript
复制
@CacheEvict(cacheNames = "dishCache", key = "#categoryId")
public void delete(Long categoryId) {
    // 删除逻辑
}
请添加图片描述
请添加图片描述

参数说明:

cacheNames:指定缓存名称 key:指定缓存的键 allEntries:是否清除所有缓存数据(true/false)

2.什么是双写一致性?双写一致性的解决方案

在项目中需要确保更新数据库数据时,Redis缓存区同步更新,从而确保两者的数据一致性,这就是"双写一致性"问题。

解决方案对比

方案

执行顺序

优点

缺点

适用场景

先删后更

删除缓存 → 更新数据库

简单易实现

数据库更新失败时缓存被误删

简单业务场景

先更后删

更新数据库 → 删除缓存

主流方案,容错性好

短暂数据不一致

推荐方案

双更同步

更新数据库 → 更新缓存

数据一致性高

并发时可能产生脏数据

对一致性要求极高

消息异步

更新数据库 → 消息队列 → 更新缓存

最可靠方案

复杂度高

大型分布式系统

推荐方案详解:先更后删策略

代码语言:javascript
复制
@Transactional
public void updateDish(DishDTO dishDTO) {
    // 1. 更新数据库
    dishMapper.update(dishDTO);
    
    // 2. 删除缓存
    redisTemplate.delete("dishCache::" + dishDTO.getCategoryId());
}

优势:

即使删除缓存失败,下次查询也会自动刷新缓存 实现简单,易于维护 适合大多数业务场景

3.redis 的三大缓存问题及解决方案

问题类型

触发条件

影响程度

解决方案

缓存穿透

访问不存在的数据

布隆过滤器、缓存空对象

缓存击穿

热点数据缓存失效

分布式锁、永不过期

缓存雪崩

大量缓存同时失效

极高

多级缓存、随机过期时间

详细问题解析

缓存穿透: 当一个不存在的数据被大量访问时,会导致大量请求直接访问数据库,浪费数据库资源,严重时导致数据库崩溃。

解决方案:

布隆过滤器:快速判断数据是否存在 缓存空对象:将空结果也缓存,设置较短过期时间

代码语言:javascript
复制
@Cacheable(cacheNames = "dishCache", key = "#id", unless = "#result == null")
public DishVO getById(Long id) {
    Dish dish = dishMapper.getById(id);
    return dish != null ? DishVO.from(dish) : null;
}

缓存击穿: 当一个高并发访问的数据的缓存失效时,导致大量请求同时访问数据库,造成数据库瞬间压力过大。

解决方案:

分布式锁:确保只有一个请求访问数据库 永不过期:设置缓存永不过期,定期更新

代码语言:javascript
复制
@Cacheable(cacheNames = "hotDishCache", key = "#id")
@Scheduled(fixedRate = 300000) // 5分钟更新一次
public List<DishVO> getHotDishes() {
    return dishMapper.getHotDishes();
}

缓存雪崩: 当某一时刻,大量缓存数据同时失效或Redis服务宕机,导致大量请求直接访问数据库,造成压力过大。

解决方案:

多级缓存:本地缓存 + Redis缓存 随机过期时间:避免缓存同时失效

代码语言:javascript
复制
@Cacheable(cacheNames = "dishCache", key = "#categoryId")
public List<DishVO> list(Long categoryId) {
    // 设置随机过期时间
    long expireTime = 3600 + new Random().nextInt(300); // 3600-3900秒
    return dishMapper.listByCategoryId(categoryId);
}

本文为苍穹外卖项目学习笔记,持续更新中…

如果我的内容对你有帮助,希望可以收获你的点赞、评论、收藏。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 今日完成任务
  • 主要功能展示
    • 实现缓存套餐功能
      • Spring Cache的使用
  • 拓充知识点
    • 1.Spring Cache 注解详解
    • 2.什么是双写一致性?双写一致性的解决方案
    • 3.redis 的三大缓存问题及解决方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档