https://chat.deepseek.com/share/mly20xe9tljbrep3j4
题目:什么是缓存击穿、缓存穿透、缓存雪崩
难度:low
标签:db/redis/cache, general/knowledge
评分:⭐⭐⭐⭐☆(4/5)
缓存击穿、穿透、雪崩,是在使用缓存过程中出现的几种常见的问题。缓存击穿是指使用了使用的数据缓存本来是应该打到缓存上的,但实际上访问的时候,这个缓存过期了,它访问到了数据库,这时候叫它就击穿了缓存,所以叫缓存击穿。缓存穿透的话,指的是使用缓存中不存在的数据去访问,数据库中本身它也不存在,这时候它实际上是一种攻击的方式,最终拿一批不存在的数据去访问数据库,个个都能穿透缓存,最终达到缓存穿透的效果,所有的请求去耗费你的资源,访问你的数据库。而缓存雪崩对应的其实更接近于服务架构本身的设计问题。雪崩是指的大批量的缓存同时过期也好,你说缓存服务出现了问题也好,都缓存无法正常响应,所有的请求直接打数据库,没有缓存层。这种情况下叫做缓存雪崩。相应的这些,面对这些问题的处理方式也各不相同。如缓存击穿,缓存击穿的话,处理方式一般是在为了防止一个请求打穿了之后,其他的请求跟风一起打到数据库,这时候基本上是单线程,在获取访问数据库的时候,加个单线程,加个锁,让缓存击穿的数据只有一条,其他数据先等待,这样其他数据都读的也都是缓存的数据,只有一条打到了数据库,没有什么时质的危害性。而缓存穿透这种的话,基本上是对数据做过滤,首先去识别这个数据的是否有效,而不是直接去让它打缓存。识别有效的话,常见的基本上是布隆过滤器,这种方式把数据加载,当然它有自己的风险问题。如果系统的防护率没那么高,可能会使用一些更简单的方式,比如说这个数据它没有没有的时候,我就直接给它缓存一下,防止它下次再打。这种可以识别处理一些类似于拿 -1 去访问你数据的问题。但是如果对方长期的使用各种不存在的数据去访问,这时候可能就要占据你大量的缓存了。这种处理方式,如果你没做处理,没有做前置的布隆过滤器那种相对的资源消耗比较大的处理,你就处理可能就人工发现去封 IP,或者是做对应的账号做一些特殊的处理,风控。然后缓存雪崩的话,常见的一个是保证设备的稳定性,设备的可持续提供的能力。另外就是对缓存的过期时间做把控。比如对缓存加一些缓存的过期时间加随机数,确保不在同一时间去统一,大量的缓存不在同一时间过期,来达到处理缓存雪崩的目的。
优点:
不足:
补充:
核心考点定位:三种问题的根因不同(单点失效 vs 无效数据 vs 批量失效),防御手段也必须差异化。
知识点拆解:
三者的组合防御:参数校验 → 布隆过滤器 → 本地缓存 → Redis 查询(命中/互斥锁重建/空值缓存)→ 缓存重建(TTL 加随机)→ DB 查询(限流熔断兜底)
考察方向:
延伸递进面试题:
面试官您好,这三种问题本质是失效模式不同:击穿是单点、穿透是无效、雪崩是批量。
缓存击穿是热点 key 过期,并发全部穿透。我用三档方案:互斥锁重建(SETNX + 短超时,其他线程短轮询读缓存)适合中等并发;逻辑过期(值里存 expireTime,物理 TTL 永不过期)适合高并发且容忍读旧;永过期 + 后台定时刷新适合核心热点数据。选哪个取决于能否接受读旧数据。
缓存穿透是请求不存在的 key,我用分层防御:入口参数校验先拦非法 ID;布隆过滤器预加载所有有效 ID,误判率控制到 1% 以内;对布隆漏网的,缓存空值 30 秒兜底。布隆有静态限制,我们定期全量重建,新增数据走 Count-Min Sketch 或 RedissonBloom 动态扩容。极端情况走风控封 IP。
缓存雪崩是批量失效或 Redis 挂,我用组合方案:TTL 加随机抖动避免同时过期;主从 + Sentinel 保证 Redis 可用;多级缓存(Caffeine + Redis)作为兜底;DB 侧接限流熔断,Sentinel 规则兜底。上线前做容量压测,确定临界值。
实际工程里这三种问题常同时出现,比如电商秒杀:热点商品 key 过期(击穿)+ 恶意刷不存在的 SKU(穿透)+ Redis 节点宕机(雪崩)。所以防御体系要分层叠加,而不是单选一种方案。