当前位置:首页 > 问答 > 正文

你说这到底是缓存穿透还是击穿?我真有点分不清楚了

(用户)说这到底是缓存穿透还是击穿?我真有点分不清楚了。

这事儿确实容易让人犯糊涂,因为它们俩乍一看挺像的,都是缓存没起到应有的作用,请求直接冲到了数据库,导致数据库压力山大,但仔细掰开来看,问题的“病根儿”和“发病”的场景是完全不一样的,咱们就用大白话,结合网上大家常聊的例子,来把它捋清楚。

先说缓存穿透:它就像是你去一个图书馆找一本根本不存在的书。

想象一下,你是个图书管理员,缓存就像是图书馆里那个最显眼、最方便的热门书架,大家常借的书都放在上面,数据库呢,就是后面那个巨大的、存放所有书籍的仓库。

有个人跑来,非要借一本叫《如何成为亿万富翁在一周内》的书(来源:常见技术社区讨论中,常以查询不存在的商品ID或用户名举例),你一听,这书名就不靠谱,你印象中图书馆压根儿就没进过这本书,于是你先在热门书架上找,肯定没有(缓存未命中),然后你不得不去后面的大仓库里翻箱倒柜,花了老鼻子劲,最后确认——果然,仓库里也没有这本书(数据库中也无此数据)。

你说这到底是缓存穿透还是击穿?我真有点分不清楚了

关键是,如果只是一个人来问一次也就算了,但要是有一大群人,或者是同一个人用机器不断生成各种稀奇古怪的、根本不存在的书名来问你(来源:常提及恶意攻击或大量非正常请求),你就会一直不停地在大仓库里做无用功,你(数据库)被这些根本不存在的请求搞得筋疲力尽,而那个热门书架(缓存)形同虚设,因为请求的数据根本不存在,永远也不会被放上去。这种“查询一个根本不存在的数据,导致请求穿透缓存直接访问数据库,并且数据库也找不到”的情况,就是缓存穿透。 它的核心危害在于大量无效查询对数据库造成的压力。

那缓存击穿又是什么呢?它更像是一本超级热门的书,偏偏在大家最想借的时候,从热门书架上被撤下来了。

还是那个图书馆,有一本超级畅销书,XXX修仙传》最新卷,平时都放在热门书架上,借的人非常多,但因为就在手边,你处理起来很快(热点数据正常缓存)。

你说这到底是缓存穿透还是击穿?我真有点分不清楚了

突然,这本书在热门书架上放的时限到了,或者因为某种原因被暂时下架了(缓存数据恰好过期),好巧不巧,就在这一刻,一大群早就等着借这本书的人同时涌到了柜台前(来源:常形容在热点数据缓存失效的瞬间,有大量并发请求同时到来)。

这下麻烦了,你发现热门书架上没有这本书,于是你只能告诉所有人:“大家等一下,我去仓库给你们拿!”然后你一个人冲向大仓库,问题是,外面等着的是成百上千个焦急的读者(高并发请求),你从仓库里把书搬出来一本,刚放到柜台上,瞬间就被借走了,但后面还有无数人在喊“我也要!”,因为你一次只能服务一个人(数据库处理能力有限),所以队伍排得老长,系统卡得要死,虽然最终你可能会把这本书重新放回热门书架(重新构建缓存),但在你从仓库取书到放回书架的这个短暂空窗期,数据库承受了巨大的、针对同一个热点数据的并发压力。这种“某个热点key在缓存过期的瞬间,大量并发请求直接打到数据库”的现象,就是缓存击穿。 它的核心危害在于对单个热点数据的超高并发访问集中在数据库上。

帮你快速区分:

  • 问谁要? 缓存穿透是问缓存和数据库要一个 根本不存在 的东西,缓存击穿是问数据库要一个 存在但缓存刚好没了 的热点东西。
  • 攻击点:穿透是面向大量不同的、无效的key进行攻击(散弹枪),击穿是集中火力攻击某一个或少数几个热点key(狙击枪)。
  • 缓存状态:穿透情况下,缓存永远不会有这个数据(除非你用特殊办法把“空值”也缓存一小会儿),击穿情况下,缓存只是暂时缺失,一旦数据从数据库取出,缓存会被重新建立。

下次再遇到这个问题,你就可以先判断:这个请求的数据,它到底存不存在?如果不存在,那大概率是穿透问题;如果存在且是个热点,只是缓存刚好失效了,那就要考虑击穿的风险了,解决它们的思路也完全不同,对付穿透,常用布隆过滤器或者缓存空对象;对付击穿,可以用互斥锁、永不过期策略或提前续期等办法,不过那就是另一个话题了,希望这个比喻能帮你把这两个概念彻底分清。