当前位置: 首页 > news >正文

Redis 缓存模式与注解缓存

目录

Cache-Aside(旁路缓存模式)

1. 工作流程

2. 三大注解

3. TTL 配置

Spring Boot 示例代码

1. 启用缓存(主类)

2. Redis 缓存配置(TTL + JSON 序列化)

3. 模拟商品服务(Service)

4. 控制器(Controller)


Cache-Aside(旁路缓存模式)

Cache 即缓存,Aside有在旁边的含义 。在这种模式下,应用程序在数据读取和写入操作时,并非直接与缓存交互,缓存像是处于应用程序数据操作的旁路位置,应用程序主要操作数据库,同时兼顾对缓存的维护,因此得名旁路缓存模式。

1. 工作流程

阶段读操作(查询)写操作(更新/删除)
第一步先查缓存先写数据库
第二步缓存没命中就查数据库再删缓存(而不是更新缓存)
第三步把查询结果写入缓存下次查询再自动回填

优点:数据一致性高、实现简单。
注意:写时要删除缓存,不要直接更新缓存,否则容易产生脏数据。

2. 三大注解

注解作用时机
@Cacheable查询时自动查缓存→回源→回写
@CacheEvict删除缓存(支持 key/全部)
@CachePut更新缓存但不影响数据库写(少用)

回源指从数据库重新取数据
回写指把刚从数据库查到的数据写回缓存,让后续的查询可以直接从缓存命中,避免再次访问数据库

@CachePut 少用的核心原因:数据不一致风险

@CachePut 的理念是方法执行后必定更新缓存

但业务逻辑中,方法执行成功 ≠ 数据库更新成功

比如方法执行了,但数据库事务回滚、数据库连接失败、乐观锁冲突等

结果缓存更新了,但数据库没更新,导致数据永久不一致
大部分更新操作需要保证数据库和缓存同时成功

3. TTL 配置

在配置类中设置:

RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10));  // 每个缓存项存活 10 分钟

防止缓存爆炸或脏数据长期存在

defaultCacheConfig()

名字里的 default = 默认

CacheConfig = 缓存配置对象
含义是创建一个默认的缓存配置(默认序列化、无过期时间)
然后我们可以在它的基础上再定制(比如加 TTL、加序列化器等)

entryTtl(...)

entry = 每个缓存条目(每个 key)

TTL = Time To Live(生存时间)
含义是为每个缓存条目设置过期时间
这里是说每个缓存项活多久

Duration 是 Java 8 的时间类,用来表示一段持续时间

ofMinutes(10) 表示 10 分钟的时长对象
所以这句返回一个代表10分钟的 Duration 实例

Spring Boot 示例代码

1. 启用缓存(主类)

@SpringBootApplication
@EnableCaching
public class RedisApplication {public static void main(String[] args) {SpringApplication.run(RedisApplication.class, args);}
}

2. Redis 缓存配置(TTL + JSON 序列化)

@Configuration
public class RedisCacheConfig {@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {    Jackson2JsonRedisSerializer<Object> serializer =new Jackson2JsonRedisSerializer<>(Object.class);RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)).entryTtl(Duration.ofMinutes(10));return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();}
}

3. 模拟商品服务(Service)

@Service
public class ProductService {private static final Map<Long, Map<String, String>> DB = new HashMap<>();static {DB.put(1L, Map.of("id", "1", "name", "Phone", "price", "1999"));DB.put(2L, Map.of("id", "2", "name", "Laptop", "price", "4999"));}@Cacheable(cacheNames = "prod", key = "#id")public Map<String, String> findById(Long id) {System.out.println("📦 查询数据库 id=" + id);try { Thread.sleep(300); } catch (InterruptedException ignored) {}return DB.get(id);}@CacheEvict(cacheNames = "prod", key = "#id")public void updatePrice(Long id, int newPrice) {System.out.println("🧾 更新价格并清除缓存 id=" + id);Map<String, String> product = DB.get(id);DB.put(id, Map.of("id", product.get("id"),"name", product.get("name"),"price", String.valueOf(newPrice)));}
}

4. 控制器(Controller)

@RestController
@RequestMapping("/prod")
public class ProductController {private final ProductService productService;public ProductController(ProductService productService) {this.productService = productService;}@GetMapping("/{id}")public Map<String, String> get(@PathVariable Long id) {return productService.findById(id);}@PostMapping("/{id}/price")public String update(@PathVariable Long id, @RequestParam int price) {productService.updatePrice(id, price);return "OK";}
}

验证步骤

1. 第一次访问:
GET http://localhost:8080/prod/1
控制台输出:📦 查询数据库 id=1
说明缓存写入成功

2. 第二次访问同一接口:
控制台没有查询数据库字样,则命中缓存 

3. 更新:
POST http://localhost:8080/prod/1/price?price=1888
控制台输出清除缓存,再访问 /prod/1 会重新回源

4. 10 分钟后 TTL 到期,再访问会自动回源刷新

http://www.dtcms.com/a/494886.html

相关文章:

  • Ansible之剧本和角色
  • 有什么平台做网站比较好河南省住房和城乡建设部网站首页
  • 靶场练习2
  • 把 1688 商品详情「搬进 MySQL」:Java 爬虫全链路实战(2025 版)
  • java内存性能优化工具Mat
  • React 18.x 学习计划 - 第四天:React Hooks深入
  • 地学考研专业选择学科地理、人文地理,还是GIS?不想考数学怎么选?
  • React 2025 完全指南:核心原理、实战技巧与性能优化
  • 大数据平台建站重庆网站制作团队
  • Linux CentOS 7 安装配置HAProxy完整指南:实现高可用负载均衡
  • 【小白笔记】PyTorch 和 Python 基础的这些问题
  • linux学习笔记(35)C语言连接mysql
  • 消息推送策略:如何在营销与用户体验间找到最佳平衡点
  • go资深之路笔记(九)kafka浅析
  • Java String 性能优化与内存管理:现代开发实战指南
  • 【软考备考】 NoSQL数据库有哪些,键值型、文档型、列族型、图数据库的特点与适用场景
  • 论《素数的几种筛法》
  • html静态页面怎么放在网站上原平的旅游网站怎么做的
  • 网页设计与网站建设作业公众号小程序制作步骤
  • 律师怎么做网站简单大气网站模板
  • 偏振相机在半导体制造的领域的应用
  • Uniapp微信小程序开发:EF Core 中级联删除
  • Java从入门到精通 - 集合框架(二)
  • 3proxy保姆级教程:WIN连接远端HTTPS代理
  • 大厂AI各走“开源”路
  • 室内装修效果图网站有哪些百度网盟推广是什么
  • grootN1 grootN1.5 gr00t安装方法以及使用(学习)
  • Typora(跨平台MarkDown编辑器) v1.12.2 中文绿色版
  • Unity开发抖音小游戏的震动
  • 团队作业——概要设计和数据库设计