先交代个背景,这仨词儿你肯定在面试题里见过,网上文章也一堆,但大多是八股文,背完就忘。其实它们是线上真实事故的高发区,搞懂了对你有实打实的好处。我当年就栽过一次:搞了个活动页,结果瞬间流量把数据库打崩了,老板脸都绿了。后来复盘才发现,那就是缓存雪崩加击穿一起凑热闹。今天我用场景给你讲,保证你记住就不忘。

穿透:查了个压根不存在的东西
穿透最容易理解:请求的数据,缓存里没有,数据库里也没有。比如按商品ID查详情,有人拿个不存在的ID反复刷,缓存永远命中不了,请求全怼到数据库上。一个人刷没啥,架不住人家写脚本循环刷,数据库分分钟被打垮。这种问题的核心是:空的东西也能把数据库累死。对策就顺着这个思路来:把空结果也缓存起来,缓个一两分钟,下次再查同样的空ID,直接命中缓存,数据库就清净了;再讲究点,用布隆过滤器在缓存前面先拦一道,不存在的key直接挡在门外。
击穿:热点数据刚好过期那一秒
击穿跟穿透一字之差,意思差远了。击穿说的是:有个数据特别火,比如秒杀商品、热搜第一,所有人都来查它,结果它的缓存正好在这一秒过期了,然后几百上千个请求同时穿到数据库。它的特点是有且只有这一个热点key在作妖,其他key都好好的。对策也很有针对性:热点数据别设过期时间,或者设了过期时间也别让它裸奔,用个互斥锁,让同一时刻只有一个请求去重建缓存,其他人等着或者先拿旧值;再就是逻辑过期,缓存里存个过期时间戳,后台线程提前刷新,前台永远拿得到数据。
说白了,击穿防的是那个明星key,别让它在换班那一瞬间被挤爆。
雪崩:一大片key集体罢工
雪崩是三个里最狠的:不是一两个key过期,而是大量key在同一时间点集体过期,或者干脆Redis整个挂了,于是所有请求一股脑冲向数据库。数据库再能扛也架不住这种场面,直接给你崩给你看。对付雪崩,招数也直接:给过期时间加上随机数,让key错开过期,别整整齐齐地一起退休;Redis本身做高可用,主从加哨兵或者集群,配好持久化,别让它轻易整个挂掉;再就是缓存失效的时候做个降级,该限流的限流,别让数据库裸奔接客。
真出事的时候,先分清是谁
线上真遇到缓存问题了,第一件事不是翻代码,是判断属于哪一类:看监控里是不是单个key流量异常,那是击穿;看是不是缓存命中率整体断崖式下跌,那是雪崩或Redis挂了;看是不是一堆不存在key的请求在刷,那是穿透。判断错了方向,折腾半天也是白搭。我当年就是没分清,把雪崩当击穿处理,加了半天锁,一点用没有,后来才反应过来是Redis那台机器内存爆了。
工程里都是组合拳,别指望一招鲜
真实系统不会只面对一种问题,穿透、击穿、雪崩经常轮着来。所以成熟的做法是一套组合防护:缓存层做高可用和持久化;过期时间加随机扰动;热点key用互斥锁或异步刷新;缓存前面加参数校验和布隆过滤;数据库前面再设个连接池上限和限流兜底。每一层单拎出来都不完美,但组合起来,哪怕缓存层全挂了,数据库也能被最后一道限流保下来,这就是工程和课本的区别。
热点key除了上锁,还能多留几手
互斥锁是防击穿的经典招,但工程上还有几个搭档值得用:一是本地缓存兜底,把最热的那几个数据在应用进程里也存一份,就算Redis瞬间抽风,本地还能扛一小会儿;二是缓存预热,大促、秒杀开始之前,把要用的热点数据提前灌进缓存,别等用户来了现生成;三是分级缓存,热点数据用更长的过期时间,冷数据短一点。这些招单独用都有局限,组合起来,热点key那点事基本就稳了。
说个我踩过的:有回活动上线,Redis里存了全量商品,想着加大内存就行,结果预热没做,零点一到流量冲进来,缓存里空空如也,全去查数据库了。后来学乖了,凡是可预见的大流量,先把数据预热好,宁可提前准备,也别等线上教你做人。
最后送句话
这三个概念记住一句口诀就够用:穿透防不存在的东西,击穿防热点key过期的瞬间,雪崩防大面积同时失效。真到排查的时候,先看监控分清是谁,再对症下药,比背一百遍定义都管用。行了,下次面试官再问你,你就拿我讲的这几个场景回他,保证他觉得你是个干过活儿的,而不是只会背书的。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!