news 2026/5/26 14:41:24

黑马点评-商户查询缓存-03_cache_consistency_and_avalanche

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
黑马点评-商户查询缓存-03_cache_consistency_and_avalanche

黑马点评商户查询缓存三:为什么更新商铺后要删缓存,而不是改缓存?

本文继续整理黑马点评 Redis 实战篇第 2 章「商户查询缓存」。

前两篇讲了普通商户缓存查询和缓存穿透。缓存能提升查询速度,但也带来一个新问题:数据源在 MySQL,查询却可能从 Redis 返回,那商铺更新后,Redis 里的旧数据怎么办?

这一篇重点讲缓存一致性:为什么常见做法是“先更新数据库,再删除缓存”,以及缓存雪崩为什么也需要提前考虑。


1. 问题背景

商铺查询接口加缓存后,读请求大致是:

查 Redis Redis 有,直接返回 Redis 没有,查 MySQL 查到后写 Redis

这条链路提升了查询性能。

但商铺数据不是永远不变的。

比如商铺可能会更新:

商铺名称 商铺地址 营业时间 评分 图片

如果数据库更新了,但 Redis 里还是旧数据,那么用户查询时命中 Redis,就会看到旧商铺信息。

这就是缓存和数据库不一致问题。


2. 我当时的困惑

我一开始最自然的想法是:

更新数据库之后,顺手把 Redis 也更新成新数据,不就一致了吗?

看起来确实合理:

更新 MySQL 更新 Redis

但实际项目里更常见的是:

更新 MySQL 删除 Redis

这就有点反直觉。

为什么不是“更新缓存”,而是“删除缓存”?


3. 正确理解:缓存不是主数据源

商户缓存这一章使用的是 Cache Aside Pattern。

在这个模式里:

MySQL 是主数据源。 Redis 是旁路缓存。

查询时,应用先查缓存,缓存没有再查数据库。

更新时,应用先更新数据库,再处理缓存。

这里的关键是:

缓存只是为了加速读,不应该承担主数据源职责。

所以更新时没必要努力维护 Redis 中每一份缓存为最新。

更简单、更常用的做法是:

数据库更新后,让缓存失效。 下一次查询时,再从数据库加载最新数据重建缓存。

4. 更新缓存 vs 删除缓存

更新数据库后,有两种常见处理方式。

第一种:更新缓存。

更新 MySQL 更新 Redis

问题是:如果一个商铺短时间内被多次更新,但没人查询,那么每次更新 Redis 都是无效写。

第二种:删除缓存。

更新 MySQL 删除 Redis

下次有人查询时:

Redis 没有 查 MySQL 写入最新数据

这更符合缓存的定位:

有人读时才重建缓存,没人读就不浪费 Redis 写操作。


5. 为什么通常先更新数据库,再删除缓存

这里有一个经典顺序问题:

先删缓存,再更新数据库? 还是先更新数据库,再删缓存?

黑马点评讲义推荐的是:

先更新数据库,再删除缓存。

如果先删除缓存,再更新数据库,可能出现这样的并发问题:

MySQLRedis线程2 查询商铺线程1 更新商铺MySQLRedis线程2 查询商铺线程1 更新商铺删除缓存查询缓存,未命中查询数据库,读到旧数据把旧数据写回缓存更新数据库为新数据

最后的结果是:

MySQL 是新数据 Redis 却被写回了旧数据

而先更新数据库,再删除缓存,出现旧数据写回缓存的概率更低。

它不是绝对没有并发问题,但在常见业务里更合理,也更简单。


6. 项目里的更新代码

项目里更新商铺的核心代码大致是:

@Transactional@OverridepublicResultupdate(Shopshop){Longid=shop.getId();if(id==null){returnResult.fail("店铺id不能为空...");}updateById(shop);stringRedisTemplate.delete(CACHE_SHOP_KEY+id);stringRedisTemplate.delete(CACHE_HOT_SHOP_KEY+id);returnResult.ok();}

这段代码有三个关键点。

第一,先校验 id。

没有 id 就不知道要更新哪个商铺,也不知道要删除哪个缓存。

第二,先更新数据库:

updateById(shop);

第三,再删除缓存:

stringRedisTemplate.delete(CACHE_SHOP_KEY+id);stringRedisTemplate.delete(CACHE_HOT_SHOP_KEY+id);

这里删除了两套缓存,是因为当前项目里已经做了“普通数据走 pass-through,热点数据走逻辑过期”的改造。

普通缓存 key:

cache:shop:{id}

热点缓存 key:

cache:shop:hot:{id}

如果只删普通缓存,不删热点缓存,热点商铺可能仍然返回旧数据。


7. 事务注解能解决 Redis 和 MySQL 的强一致吗?

代码上有:

@Transactional

初学时容易以为:

加了事务,数据库更新和 Redis 删除就一定同时成功或失败。

这个理解不准确。

@Transactional主要管理的是数据库事务。

Redis 删除操作不天然纳入 MySQL 本地事务。

所以这里更准确的理解是:

数据库更新本身需要事务保护。 缓存删除是更新数据库后的配套动作。

在真实分布式系统中,如果要更严格保证数据库和缓存一致,可能会引入消息队列、订阅 binlog、重试机制等方案。

但在这一章里,我们先掌握最常用、最简单的 Cache Aside 做法。


8. 更新后的查询流程

删除缓存后,下一次查询会重新走缓存重建。

更新商铺请求

更新 MySQL

删除 Redis 普通缓存

删除 Redis 热点缓存

后续查询商铺

Redis 未命中

查询 MySQL 最新数据

写入 Redis

返回最新商铺信息

这就是删除缓存的价值:

不主动维护缓存最新,而是让下一次查询自然重建最新缓存。


9. 顺带理解缓存雪崩

这一章还讲了缓存雪崩。

缓存雪崩是指:

同一时间大量缓存 key 失效,或者 Redis 服务不可用,导致大量请求同时打到数据库。

比如我们给大量商铺设置了完全相同的 TTL:

cache:shop:1 30分钟后过期 cache:shop:2 30分钟后过期 cache:shop:3 30分钟后过期 ...

如果它们在同一时刻过期,大量请求就可能同时回源 MySQL。

流程如下:

大量缓存 key 同时过期

大量请求查 Redis 未命中

请求集中打到 MySQL

数据库压力剧增

接口变慢甚至不可用

常见解决方式包括:

给 TTL 增加随机值,避免同一时间失效 提高 Redis 可用性,比如集群或主从 业务层限流降级 使用多级缓存

10. 易错点

第一个易错点:以为缓存必须和数据库实时完全一致。

大多数缓存场景追求的是最终一致,而不是每一毫秒都强一致。

第二个易错点:更新数据库后更新缓存。

不是不能做,但对于读多写少的缓存场景,删除缓存通常更简单,避免无效写。

第三个易错点:先删缓存再更新数据库。

这种顺序在并发下更容易把旧数据重新写回缓存。

第四个易错点:以为@Transactional能把 Redis 删除也纳入 MySQL 本地事务。

它主要管数据库事务,Redis 操作仍然需要额外考虑失败风险。

第五个易错点:忽略热点缓存。

如果系统里同时有普通缓存和热点缓存,更新时必须都处理。


11. 面试怎么回答

如果面试官问:

缓存和数据库不一致怎么解决?

可以回答:

常见做法是 Cache Aside Pattern。 查询时先查缓存,未命中再查数据库并写入缓存。 更新时先更新数据库,再删除缓存。 这样下一次查询缓存未命中时,会从数据库读取最新数据并重建缓存。

如果问:

为什么删除缓存而不是更新缓存?

可以回答:

因为缓存是为了加速读,不是主数据源。 如果每次更新数据库都同步更新缓存,可能产生很多无效写。 删除缓存更简单,后续真正有人查询时再从数据库加载最新数据写入缓存。

如果问:

什么是缓存雪崩?

可以回答:

缓存雪崩是指同一时间大量缓存 key 失效,或者 Redis 整体不可用,导致大量请求绕过缓存直接访问数据库。 常见解决方案包括给 TTL 添加随机值、提高 Redis 高可用、限流降级和多级缓存。

12. 总结

这一篇最重要的是记住:

在 Cache Aside 模式下,更新商铺时通常先更新数据库,再删除缓存;下一次查询再重建缓存。

删除缓存不是偷懒,而是符合缓存的定位:

MySQL 负责保存真实数据。 Redis 负责加速读取。 缓存失效后,由下一次查询重建。

到这里,普通缓存查询、缓存穿透、缓存一致性、缓存雪崩的基本思路已经串起来了。

但还有一个更危险的问题:

如果某个热门商铺 key 过期,大量请求同时来查,会发生什么?

这就是下一篇的缓存击穿和互斥锁。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 14:41:22

零碳园区的数据如何分析与应用

在“双碳”战略纵深推进的背景下,零碳园区已成为产业绿色转型的核心载体,而数据作为零碳转型的“核心生产要素”,贯穿园区规划、建设、运营、优化全生命周期。零碳园区的数据涵盖能源、碳排、设备、环境等多维度,其价值不在于“采…

作者头像 李华
网站建设 2026/5/26 14:41:00

干货文案:我们这样写出爆款

你有没有发现,那些让人忍不住收藏、分享的文章,往往都有一个共同点——它们全是干货。不是空洞的道理,不是鸡汤,而是实实在在能拿来用的方法。今天我们就来聊聊,怎么写出真正的干货文案。抓住痛点,从问题出…

作者头像 李华
网站建设 2026/5/26 14:37:02

告别手动操作!用Python脚本批量处理DICOM转NIfTI(dcm2niix实战)

医学影像自动化处理:Python与dcm2niix高效批量转换实战指南医学影像研究常面临海量DICOM数据处理的挑战。想象一下,当你手头有数百个患者扫描序列,每个序列包含几十甚至上百个DICOM文件时,手动逐个转换不仅效率低下,还…

作者头像 李华
网站建设 2026/5/26 14:36:20

闭环神经调控系统:从癫痫治疗到智能神经调节的技术解析

1. 项目概述:从开环到闭环的神经调控革命在神经科学和临床医学的交叉领域,神经调控技术正经历一场深刻的范式转变。作为一名长期关注神经工程与临床转化的一线从业者,我亲眼见证了设备从简单的“电刺激器”演变为集感知、分析与干预于一体的智…

作者头像 李华
网站建设 2026/5/26 14:32:04

企业级IT服务管理实战指南:iTop开源CMDB深度解析

企业级IT服务管理实战指南:iTop开源CMDB深度解析 【免费下载链接】iTop A simple, web based CMDB & IT Service Management tool 项目地址: https://gitcode.com/gh_mirrors/it/iTop iTop是一款基于Web的开源IT服务管理平台,提供完整的配置…

作者头像 李华
网站建设 2026/5/26 14:30:04

揭开数控机床的神秘面纱:从三轴到五轴,一文读懂核心差异

于现代制造业里, 数⁠控机床乃是精密加工得以开展的基础支撑所在, 从我们平常所使用‌的手机‍外壳, 到航空航天领域那些构造繁复的零部件, 在其背后, 全都离不开数控⁠机床高效运行这一环节。然‍而, “三轴”、“四轴”、‍“五‍轴”这些‍具备专业性的‍术语, 常常会致使非…

作者头像 李华