news 2026/4/14 14:17:44

PHP的缓存击穿 = 缓存穿透?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP的缓存击穿 = 缓存穿透?

缓存击穿和缓存穿透是两个截然不同的概念,它们发生的场景、原因和解决方案都有本质区别。

核心结论

  • 缓存穿透:访问一个根本不存在的数据。相当于你要找一个不存在的人,查了通讯录(缓存)没找到,又去翻了全市户口本(数据库)还是没找到。这是“数据存在性”问题。
  • 缓存击穿:访问一个存在但刚好过期的热点数据。相当于你要找市长,但市长刚好在开会(缓存过期),导致所有电话都打到会议室(数据库)。这是“热点数据并发”问题。

第一层:缓存穿透的“庖丁解牛”

攻击原理

攻击者故意频繁请求一个数据库中根本不存在的数据

攻击流程
  1. 请求缓存:cache.get('user_9999999')->缓存未命中
  2. 请求数据库:SELECT * FROM users WHERE id = 9999999->数据库查询为空
  3. 由于数据不存在,无法写入缓存(或者只能缓存一个短暂的空值)
  4. 下一个相同请求到来,重复步骤1-3
造成危害
  • 数据库压力:恶意请求会绕过缓存,直接冲击数据库,可能导致数据库宕机。
  • 资源浪费:大量无效查询消耗系统资源。
解决方案
  1. 缓存空对象:即使数据库查询为空,也在缓存中存储一个空值(如NULL)并设置一个较短的过期时间(如1-5分钟)。
    $user=$cache->get('user_'.$id);if($user===null){$user=$db->query("SELECT * FROM users WHERE id =$id");if(!$user){// 数据库也没有,缓存一个空对象,避免频繁查询数据库$cache->set('user_'.$id,false,300);// 缓存5分钟}else{$cache->set('user_'.$id,$user,3600);}}return$user!==false?$user:null;
  2. 布隆过滤器:在缓存前加一层布隆过滤器,快速判断数据是否可能存在。如果布隆过滤器说数据不存在,则直接返回,不查询缓存和数据库。

第二层:缓存击穿的“庖丁解牛”

发生场景

某个热点数据(如热门商品信息、明星微博)在缓存中过期瞬间,有大量并发请求同时到来。

击穿流程
  1. 热点Key缓存过期:cache.get('hot_product_123')->缓存过期
  2. 瞬间有数万个并发请求同时发现缓存失效
  3. 数万个请求同时去查询数据库:SELECT * FROM products WHERE id = 123
  4. 数据库瞬间承受巨大压力,可能被打挂
造成危害
  • 数据库雪崩:热点数据的并发查询可能导致数据库连接池耗尽、CPU飙高。
  • 系统瘫痪:整个服务因一个热点Key的失效而不可用。
解决方案
  1. 互斥锁:第一个发现缓存过期的请求获取分布式锁,然后查询数据库并重建缓存,其他请求等待。
    publicfunctiongetProduct($id){$key='product_'.$id;$product=$cache->get($key);if($product===null){// 缓存失效$lockKey='lock:'.$key;if($cache->add($lockKey,1,10)){// 尝试获取锁// 获取锁成功,查询数据库$product=$db->query("SELECT * FROM products WHERE id =$id");$cache->set($key,$product,3600);$cache->delete($lockKey);// 释放锁}else{// 没获取到锁,等待重试或返回默认值usleep(100000);// 等待100msreturn$this->getProduct($id);// 重试}}return$product;}
  2. 永不过期+逻辑过期:缓存不设置过期时间,但值中包含逻辑过期时间。后台任务定期更新缓存。
  3. 热点数据预加载:在缓存过期前,提前异步刷新缓存。

第三层:对比总结表

特征缓存穿透缓存击穿
攻击目标不存在的数据存在但过期的高并发数据
请求性质恶意攻击或错误请求正常的用户请求
并发量可能不高,但持续不断瞬间高并发
根本问题数据不存在性判断热点数据并发重建
解决方案1. 缓存空值
2. 布隆过滤器
1. 互斥锁
2. 逻辑过期

第四层:实战场景示例

缓存穿透场景

场景:攻击者用脚本遍历用户ID:/api/user/1,/api/user/2, …,/api/user/1000000
结果:大部分ID都不存在,每次请求都穿透到数据库。

缓存击穿场景

场景:双十一零点,数万用户同时点击"秒杀iPhone"商品页面,该商品缓存刚好在11:59:59过期。
结果:零点瞬间数万请求同时打向数据库查询同一商品信息。


第五层:还有一个"缓存雪崩"

为了完整起见,我们提一下相关的第三个概念:

缓存雪崩大量的缓存Key在同一时间点或时间段内集中过期,导致所有请求都落到数据库上。

  • 与击穿的区别:击穿是单个热点Key,雪崩是大量Key同时失效
  • 解决方案:给缓存过期时间加上随机值,避免同时过期。

终极总结

  • 穿透:查无此数据→ 用布隆过滤器缓存空值解决
  • 击穿:查热点数据但缓存刚好失效 → 用互斥锁解决
  • 雪崩大量数据缓存同时失效 → 用随机过期时间解决

理解这三者的区别,是设计高可用缓存架构的基础。它们虽然都导致数据库压力,但病因不同,治疗方案也完全不同。

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

3分钟搞定Kazam:Linux最强录屏工具完整安装教程

3分钟搞定Kazam:Linux最强录屏工具完整安装教程 【免费下载链接】kazam Kazam - Linux Desktop Screen Recorder and Broadcaster 项目地址: https://gitcode.com/gh_mirrors/kaz/kazam 还在为Linux系统寻找简单易用的屏幕录制工具而困扰吗?Kazam…

作者头像 李华
网站建设 2026/4/13 18:44:25

企业级文本智能实战指南:从数据到决策的价值挖掘

企业级文本智能实战指南:从数据到决策的价值挖掘 【免费下载链接】monkeylearn-python Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps. 项目地址: https://gitcode…

作者头像 李华
网站建设 2026/4/6 13:19:31

DsHidMini深度指南:让DualShock 3手柄在Windows上重获新生

DsHidMini深度指南:让DualShock 3手柄在Windows上重获新生 【免费下载链接】DsHidMini Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers 项目地址: https://gitcode.com/gh_mirrors/ds/DsHidMini 作为一名游戏爱好者,你是否…

作者头像 李华
网站建设 2026/4/10 5:34:24

如何通过Gephi实现从数据混乱到洞察清晰的三步进阶

如何通过Gephi实现从数据混乱到洞察清晰的三步进阶 【免费下载链接】gephi Gephi - The Open Graph Viz Platform 项目地址: https://gitcode.com/gh_mirrors/ge/gephi 你是否曾经面对复杂的网络数据感到无从下手?看着密密麻麻的节点和连线,却无法…

作者头像 李华
网站建设 2026/4/10 23:43:39

云端游戏桥接方案:便携终端跨平台串流终极指南

云端游戏桥接方案:便携终端跨平台串流终极指南 【免费下载链接】Moonlight-Switch Moonlight port for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/mo/Moonlight-Switch 想要在便携式游戏终端上畅玩PC大作?云端游戏桥接方案让这成…

作者头像 李华