Redis如何在高并发环境避免缓存击穿引起的数据库崩溃
Redis如何在高并发环境避免缓存击穿引起的数据库崩溃

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
先明确一个核心概念:缓存击穿。它特指某个热点 key 在 Redis 中过期的瞬间,大量并发请求同时穿透缓存,直接冲击数据库。这既不同于大面积的缓存雪崩,也区别于查询不存在数据的缓存穿透,而是单个高热 key 在“过期真空期”引发的瞬时洪峰,破坏力集中,极易成为系统瓶颈。
缓存击穿是什么,为什么它会压垮数据库
想象一下这样的场景:一个秒杀商品的详情页、热搜榜单的第一名,或者一个活动倒计时的配置。这些 key 承载着巨大的访问量,一旦其生存时间设置不当或未能及时续期,过期的那一刻,几十甚至上百个请求便会如潮水般涌向数据库。
关键在于,当 GET 命令返回 null 后,多个线程或进程几乎会同时执行 SELECT ... FROM db 查询,紧接着再执行 SET 写回缓存。这一连串操作,瞬间就能打满数据库连接池,导致慢查询堆积,最终拖垮整个服务。可以说,缓存击穿是典型的高并发场景下的“单点爆破”问题。
用互斥锁(Mutex Lock)控制重建缓存的唯一性
解决思路很直观:只允许一个请求去数据库查询并写回缓存,其他请求则等待这个结果,而不是各自为战。Redis 本身虽然没有阻塞式锁,但我们可以巧妙地利用 SET 命令的 NX 和 EX 参数来实现原子性的加锁操作。
这里有个常见的误区:先 GET 判断锁是否存在,再 SET 加锁。这中间存在竞态条件,并非原子操作。正确做法是一步到位:
SET lock:goods:1001 "1" NX EX 30
如果返回 OK,恭喜,抢锁成功;如果返回 (nil),说明锁已被占用,当前请求就应该进入轮询,不断尝试 GET goods:1001 直到命中缓存或等待超时。
有几个细节必须注意:
- 锁的过期时间要足够:
EX 30设置的30秒必须明显长于“数据库查询+写缓存”的总耗时,否则锁提前释放,会导致重复重建,前功尽弃。 - 安全释放锁:业务代码中一定要记得
DEL lock:goods:1001,但不能简单地在 finally 块里删除。必须确保删除的是自己加的锁,防止误删他人持有的锁。推荐使用 Lua 脚本来保证“判断+删除”的原子性。 - 设置合理的等待策略:轮询间隔建议在 10–50 毫秒,总等待时间上限可设为 200 毫秒。一旦超时,应降级为直接查询数据库,避免所有请求无限等待,引发雪球效应。
用逻辑过期(Logical Expiration)替代物理 TTL
物理过期依赖 EXPIRE 命令,失效点不可控。而逻辑过期则将过期时间隐藏在 value 内部,例如存储一个 JSON 结构:{"data":"xxx","expireAt":1717023456}。每次读取时,先检查 expireAt 字段是否已过期,再决定是否触发异步刷新。
这样做的好处显而易见:key 在 Redis 中永不过期,从根本上规避了击穿风险。刷新动作由第一个发现逻辑过期的请求触发,并且是异步执行的,不会阻塞后续请求——它们仍然可以返回旧的、可用的数据。
具体实操时,要把握这几个要点:
- 写入方式:使用
SET goods:1001 "{...}"(不带EX参数),过期逻辑完全由程序控制。 - 刷新必须异步:如果将刷新操作放在同步流程中,就又变回了阻塞模式。应该使用线程池或消息队列进行解耦。
- 处理刷新失败:如果连续几次异步刷新数据库都超时或失败,应适当延长逻辑过期时间,避免短时间内反复触发无效的刷新请求。
- 注意时钟一致性:所有服务节点的系统时间偏差不能太大,否则基于
expireAt的时间判断就会失准。
兜底方案:本地缓存 + 熔断限流
要知道,Redis 本身也是一个远程服务。万一它出现抖动或网络分区,仅仅依赖分布式锁可能也无济于事。因此,必须在应用层再加一道保险。
可以在 JVM 内存中使用如 Caffeine 或 Gua va Cache 这样的本地缓存,来存储热点 key 的“是否正在重建”状态。例如:cache.put("rebuilding:goods:1001", true, 10, TimeUnit.SECONDS)。这样,即使 Redis 暂时不可用,应用也能快速判断并拒绝重复的重建请求。
同时,在数据访问层对目标数据库表施加熔断限流措施,例如集成 Hystrix 或 Sentinel。当数据库查询在短时间内失败率超过阈值(比如5秒内失败率超50%),熔断器会自动开启,后续请求直接返回降级数据(如默认值或缓存旧值),为数据库争取宝贵的恢复时间。
最后,还有一个容易被忽略但至关重要的点:缓存重建失败的日志必须单独监控和告警。不能让它混在普通的错误日志里。因为“查不到数据→写入空值缓存→下次直接返回空”这条链路,表面上风平浪静,实际上业务语义已经丢失,需要立即介入处理。
相关攻略
预测市场的真相:是群体智慧,还是少数人的游戏? 说起预测市场,很多人脑海里会立刻浮现出“群体智慧”这个词。成千上万的用户对事件反赌,最终价格似乎总能精准反映现实概率——这听起来像是民主化预测的完美典范。但最近一项来自伦敦商学院和耶鲁大学的研究,却给这个浪漫的想象泼了一盆冷水。 研究团队发现,像Pol
伊朗议员警告:若安全受威胁,波斯湾航道或陷动荡 伊朗议员法达侯赛因·马利基近日发出警告,称如果伊朗的沿海安全受到威胁,波斯湾和阿曼海将出现不安全局势。这无疑给该地区的航运前景蒙上了一层阴影。与此同时,市场对于霍尔木兹海峡交通将于5月15日恢复正常的预期,也出现了微妙变化,目前概率为14 5%。是的,
Oracle RAC归档日志全面检查指南:节点级验证与线程归属深度解析 在Oracle RAC集群环境中,归档日志的配置与状态检查是一项需要精细化操作的关键任务。它要求数据库管理员必须对每个节点逐一进行归档模式、路径设置、日志生成状态的审查,并深刻理解日志线程归属的核心逻辑。检查的核心流程是:首先通
解决RMAN恢复时日志文件名冲突引发的 ORA-01157 错误 在使用RMAN执行数据库恢复操作时,若目标磁盘上已存在同名的在线重做日志文件(例如 redo01 log),恢复进程常会中断并抛出 ORA-01157: cannot identify lock data file 错误。值得注意的是
SQL如何查询用户连续达标的天数:窗口函数状态机模型 说起查询“连续达标”天数,很多人的第一反应可能是用日期相减。但这里有个本质问题需要先想清楚:我们到底在识别什么? “连续达标”的本质是识别不间断的满足条件时间序列,需用LAG()判断状态延续性并用SUM() OVER构造段ID,而非依赖日期相减。
热门专题
热门推荐
我国刀具市场发展调研报告 在当今制造业持续升级的背景下,市场调研报告的重要性日益凸显。一份结构清晰、数据翔实的报告,能为决策提供关键参考。以下这份关于我国刀具市场的调研报告,旨在梳理现状、剖析问题,并为未来发展提供借鉴。 当前,国内刀具年销售额约为145亿元,其中硬质合金刀具占比不足25%。这一比例
国内首份空净市场调研报告 在公众健康意识日益增强的今天,市场报告的重要性不言而喻。一份结构清晰、数据翔实的报告,能为行业描绘出精准的航图。那么,一份优秀的市场调研报告究竟该如何呈现?近期发布的这份国内空气净化器行业蓝皮书,或许能提供一个范本。 市场增长的势头有多强劲?数据显示,国内空气净化器市场正驶
水利工程供水管理调研报告 在各类报告日益成为工作常态的今天,撰写一份扎实的调研报告,关键在于厘清现状、找准问题、提出思路。这份关于水利工程供水管理的报告,旨在系统梳理情况,为后续决策提供参考。 一、基本情况 横跨区域的**水库及八座枢纽拦河闸,构成了**运河流域防洪与兴利供水的骨干工程体系。自投入运
财产保全申请书范本 一份规范的财产保全申请书,是启动财产保全程序的关键文书。其核心在于清晰、准确地列明各方信息、诉求与依据。通常,申请书的结构是固定的,但具体内容需要根据案件事实来填充。下面,我们通过几个典型的范本来拆解其中的要点。 篇一:通用格式范本 首先来看一个通用模板。这个模板清晰地勾勒出了申
“防台抗台”活动由学院的积极分子组成,他们踊跃报名,利用暑期时间奉献自己的青春,为社会尽一份力量。 带队的学院分团委书记吕老师点出了活动的深层价值:这不仅是一次能力锻炼,更是学生认识社会、融入社会并最终回馈社会的关键一步。经过这番历练,团队友谊愈发坚固,协作精神显著增强,感恩之心也油然而生。 青春洋





