主题
对比小林《什么是缓存雪崩、击穿、穿透》、JavaGuide Redis 生产问题与面渣逆袭《Redis 缓存设计》(侧边栏进入)。
多版对比
定义边界,三方一致(JG 的对照最利落):用「key 在不在 DB」划界——穿透是缓存和 DB 都没有(恶意打不存在 key);击穿是 DB 有、某个热点 key 恰好过期(雪崩的子集);雪崩是大量 key 同时过期或 Redis 整体宕机。
方案组合的差异:小林按诱因分治最细——雪崩分「同时过期」(随机过期时间、互斥锁务必带超时、双 key:主 key 带过期 + 备 key 永久、后台定时更新兼做预热)和「Redis 宕机」(熔断限流 + 主从集群);穿透三法:入口拦非法请求、缓存空值/默认值、布隆过滤器(判无必无、判有未必有)。JG 补工程细节:缓空对象要设短过期(黑客换 key 就失效)、布隆过滤器百万元素约 122KB、击穿方案给出推荐度(预热 > 互斥锁看情况 > 永不过期不推荐)、预热用 xxl-job 定时或 Kafka 异步。面渣补盲区:缓空对象的两大副作用(内存膨胀、与 DB 短窗不一致需异步清理)、布隆不支持删除、热 key 打散 + 二级缓存、Facebook 3000 节点的「缓存无底洞」案例。
相关话题:小林另有缓存污染一篇——LRU 挡不住一次性扫描,Redis 4.0 用 LFU 记访问频次对抗。
最优题解
三个问题一句话区分:穿透是「查不存在的数据」,缓存和 DB 都没有,恶意请求绕过缓存直打 DB;击穿是「一个热点 key 过期」,瞬间流量全压到 DB;雪崩是「大量 key 同时过期或 Redis 挂了」,DB 被整体冲垮。
治理是组合拳:穿透——入口校验拦非法参数、把空结果也缓存起来(短过期)让恶意 key 也能命中、数据集确定且较大的用布隆过滤器挡在缓存前;击穿——热点 key 用互斥锁重建(只放一个请求去查 DB,且锁必须带超时)或逻辑过期不真删,配合提前预热;雪崩——过期时间加随机值打散、Redis 上主从集群 + 熔断限流兜底、重要数据预热和多级缓存。选型时先问流量特征:恶意攻击优先布隆和入口拦截,业务热点优先互斥锁和预热。
追问链
追问:布隆过滤器为什么会有误判?能删除吗? 参考答:多个哈希函数把 key 映射进位数组,不同 key 可能共享位——判「无」必无、判「有」可能有;标准布隆不支持删除(位是共享的),要删除用计数布隆或布谷鸟过滤器,或定期重建。
追问:互斥锁重建热点 key,等待的请求怎么办? 参考答:拿不到锁的请求先返回旧值/默认值或短暂重试,而不是都阻塞——锁只保证一个请求去查 DB;配合逻辑过期(过期后异步重建、先返回旧值)可以把阻塞完全去掉。
我的理解
这题最容易答成「方案罗列」。层次在于:①定义用「key 在不在 DB」一句话钉死边界;②方案按「问题诱因」对应而不是平铺——随机过期治雪崩、互斥锁治击穿、布隆治穿透;③主动补成本面(缓空的内存与一致性副作用、布隆的误判与不可删)。面渣的「无底洞」和小林的「缓存污染/LFU」是拉开差距的展开点。