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

Redis之缓存更新策略

缓存更新策略

在这里插入图片描述

文章目录

  • 缓存更新策略
    • 一、策略对比
    • 二、常见的缓存更新策略
    • 三、如何选择策略
    • 四、实际应用示例
    • 五、使用 Cache-Aside + TTL 的方式,实现缓存商铺信息详情
      • 1.引入StringRedisTemplate
      • 2.将查询商铺信息加入缓存
      • 3.更新商铺信息时移除缓存
      • 总结
    • 六、注意事项

一、策略对比

内存淘汰超时剔除主动更新
说明不用自己维护,
利用Redis的内存淘汰机制,
当内存不足时自动淘汰部分数据。下次查询时更新缓存。
给缓存数据添加TTL时间,
到期后自动删除缓存。
下次查询时更新缓存。
编写业务逻辑,
在修改数据库的同时,更新缓存
一致性一般
维护成本

业务场景

  • 低一致性需求:使用内存淘汰机制。例如商铺类型的查询缓存
  • 高一致性需求:主动更新,并以超时剔除作为兜底方案。例如店铺详情查询的缓存

二、常见的缓存更新策略

  1. Cache Aside Pattern旁路缓存模式):由缓存的调用者,在更新数据库的同时更新缓存。
    • 原理
      • 读操作:先查询缓存,若命中则直接返回;未命中则从数据库加载数据并写入缓存。
      • 写操作:先更新数据库,再删除缓存(或更新缓存)。
    • 优点:简单易实现,适用于大多数场景。
    • 缺点:可能存在短暂的数据不一致(如并发写入导致脏数据)。
    • 场景:读多写少、对一致性要求不高的场景。
  2. Read / Write Through Pattern读穿/写穿):缓存与数据库整合为一个服务,由服务来维护一致性。调用者调用该服务,无需关心缓存一致性问题。
    • 读穿透(Read-Through)
      • 当缓存未命中时,由缓存服务自动从数据库加载数据并回填缓存 。
    • 写穿透(Write-Through)
      • 数据更新时,同时写入缓存和数据库,保证两者同步。
    • 优点:对业务透明,数据一致性高。
    • 缺点:写操作延迟较高,依赖缓存服务的可靠性。
    • 场景:强一致性要求的场景。
  3. Write Behind Caching Pattern异步写回):调用者只操作缓存,由其他线程异步地将缓存数据持久化到数据库,保证最终一致性。
    • 原理
      • 写操作仅更新缓存,异步批量将数据持久化到数据库。
    • 优点:写性能极高,减少数据库压力。
    • 缺点:存在数据丢失风险(如系统崩溃时为同步完成的数据)。
    • 场景:允许短暂不一致、写密集型场景(如日志系统)。
  4. 被动更新(TTL刷新)
    • 原理
      • 为缓存设置过期时间(Time-To-Live,TTL),到期后自动失效并从数据库重新加载。
    • 优点:实现简单,避免长期脏数据。
    • 缺点:无法主动控制更新实际,可能出现缓存雪崩(大量缓存同时失效)。
    • 场景:数据变动频率较低的场景。
  5. 主动更新(事件驱动)
    • 原理
      • 当数据库数据变更时(如通过消息队列或出发期),主动通知应用层更新或删除对应缓存。
    • 优点:实时性高,减少无效查询。
    • 缺点:依赖外部系统协同,复杂度较高。
    • 场景:分布式系统中强一致性要求的场景(如电商库存更新)。

注意在使用Cache Aside Pattern方式的工程中,操作缓存和数据库时有三个问题需要考虑

  1. 删除缓存还是更新缓存?
    • 更新缓存:每次更新数据库都更新缓存,无效写操作较多
    • 删除缓存【推荐】:更新数据库时让缓存失效,查询时再更新缓存
  2. 如何保证缓存与数据库的操作同时成功或同时失败?
    • 单体系统:将缓存与数据库操作放在一个事务
    • 分布式系统,利用TCC等分布式事务方案
  3. 先操作缓存还是先操作数据库
    • 先删除缓存,再操作数据库
    • 先操作数据库,再删除缓存 【推荐】

三、如何选择策略

  • 数据一致性要求:强一致性选 Write-Through 或主动更新;弱一致性可选 Cache-Aside 或 TTL。
  • 读写比例:读多写少优先 Cache-Aside;写多考虑 Write-Behind。
  • 系统复杂度:简单场景用 TTL 或 Cache-Aside;复杂场景用事件驱动。
  • 性能需求:高频写入可用 Write-Behind 降低延迟。

四、实际应用示例

  • 电商商品详情页:使用 Cache-Aside + TTL,配合消息队列主动更新热点商品。
  • 社交点赞数统计:采用 Write-Behind 异步更新数据库,保证快速响应。
  • 全局配置信息:Read-Through 确保每次读取都是最新配置。

五、使用 Cache-Aside + TTL 的方式,实现缓存商铺信息详情

1.引入StringRedisTemplate

    @Resourceprivate StringRedisTemplate stringRedisTemplate;

2.将查询商铺信息加入缓存

    @Overridepublic Result queryById(Long id) {// 1.从redis查询商铺缓存String key = CACHE_SHOP_KEY + id;String shopJson = stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {// 3.存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}// 4.不存在,根据id查询数据库Shop shop = getById(id);if (shop == null) {// 5.数据库不存在,返回错误return Result.fail("店铺不存在!");}// 6.存在,写入redis,加入过期时间stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop);}

3.更新商铺信息时移除缓存

    @Overridepublic Result update(Shop shop) {if (shop.getId() == null) {return Result.fail("店铺id不能为空!");}// 1.更新数据库updateById(shop);// 2.删除缓存stringRedisTemplate.delete(CACHE_SHOP_KEY + shop.getId());return Result.ok();}

总结

使用 Cache-Aside + TTL 缓存更新策略的最佳实践方案:

  1. 低一致性需求:使用Redis自带的内存淘汰机制
  2. 高一致性需求:主动更新,并以超时剔除作为兜底方案
    • 读操作:
      • 缓存命中则直接返回
      • 缓存未命中则查询数据库,并写入缓存,设定超时时间
    • 写操作:
      • 先写数据库,然后再删除缓存
      • 要确保数据库与缓存操作的原子性

六、注意事项

  • 缓存穿透:恶意请求不存在的 key,可通过布隆过滤器防御。
  • 缓存雪崩:大量 Key 同时失效,需设置随机 TTL 或禁用失效时间。
  • 缓存击穿:热点 Key 失效瞬间高并发,可用互斥锁(Mutex Luck)保护。

缓存更新策略的选择需结合业务场景、数据特点和技术架构综合权衡,没有绝对的最优解,只有最适合的方案。


http://www.mrgr.cn/news/98206.html

相关文章:

  • Ubuntu系统美化
  • 回顾CSA,CSA复习
  • SpringAi 会话记忆功能
  • C++ 入门六:多态 —— 同一接口的多种实现之道
  • Spring Boot集成Nacos
  • 【BEPU V1物理】BEPUphysics v1 入门指南 汉化笔记#1
  • 哈希表-算法小结
  • 02_通过调用硅基流动平台deepseekapi按输入的标题生成文章
  • C. Robin Hood in Town思考与理解
  • 【前端】webpack一本通
  • 【Linux】单例模式及其在线程池中的应用
  • C++ STL及Python中等效实现
  • Linux 内核知识体系
  • 【SQL Server 2017】封闭网络下,数据调研所有数据表实战(提效400%)
  • 【langchain库名解析】
  • vue周边库安装与开发者工具(vue系列二)
  • 学习MySQL的第八天
  • Unity 动画
  • Compose笔记(十六)--ExoPlayer
  • 数据结构day05