张工盯着监控大屏,CPU曲线在凌晨2:03分垂直起飞。十万条查询同时撞向数据库,Redis连接池却安静得像在装睡——这不是攻击,是他亲手埋下的定时炸弹:所有商品缓存Key的过期时间,被设成了同一个Unix时间戳。

一张图看懂:缓存失效的三重暴击

打开网易新闻 查看精彩图片

双十一零点抢券卡顿、秒杀页面反复报错,后台往往在经历三种连环故障。有人用脚本狂刷不存在的用户ID(穿透);爆款商品缓存过期的毫秒间被上万请求凿穿(击穿);整个商品库缓存Key在整点集体失效(雪崩)。三者环环相扣,却各有解法。

原文把这三类故障比作"真实可复现、可定位、可防御的典型故障链"。对25-40岁的后端工程师来说,这比任何架构理论都值钱——因为监控告警响起时,没人给你翻教科书的时间。

穿透:用布隆过滤器拦截"幽灵查询"

查询根本不存在的数据,比如user:999999999,缓存无记录,请求直冲数据库。黑产脚本最喜欢这种漏洞:每秒1万次无效查询,DB瞬间变筛子。

原文给出的Python示例很直白——布隆过滤器做存在性前置校验,空值做短期缓存。核心就两点:让"不存在"止步于缓存层,别让数据库为幽灵数据买单。

作者提到一次真实事故:未对注册手机号做空值缓存,黑产遍历138****0001~138****9999,DB连接数10秒飙至2000+,服务全面超时。数字精确到秒级,没有"瞬间飙升"这种模糊表述。

击穿:给热点数据加一把"原子锁"

超高频Key恰好过期,1000个线程同时执行SET,争抢重建。原文用了一个精准场景:GET hot_item返回nil的刹那,并发请求穿透缓存,数据库CPU飙升。

解法是用Redis的SETNX实现分布式锁,带自动过期防死锁,二次检查防止重复重建,异常必释放。锁粒度最小化、自动过期、二次检查、异常必释放——四个关键点,少一个都是坑。

代码示例里有个细节:未抢到锁的线程短暂等待0.01秒后重试,或返回旧缓存/降级数据。这不是优雅降级,是保命降级。

雪崩:别让缓存"集体休眠"

大量Key设置相同过期时间,到期后集中失效,流量洪峰同步涌向数据库。张工凌晨两点的悲剧,根因在此。

根治方案分两档:普通数据用"基础TTL+随机抖动",核心数据用"逻辑永不过期+异步刷新"。原文的Python示例里,抖动范围是±10%,保底10分钟;后台任务每30分钟主动更新一次。

口诀很土但有用:不设固定过期时间,只设"基础TTL+随机抖动";核心数据宁可冗余更新,也不集体断供。

监控是最后一道哨兵

原文把监控定位得很克制:"不是锦上添花,而是故障前的最后一道哨兵"。没有夸大成"核心壁垒",也没有降级成"可选方案"。

三道裂缝的解法总结得干脆:存在性校验、热点保护、过期分散。缓存不是银弹,是需要精心设计的防护体系——这句话放在结尾,像是对所有迷信"加个Redis就完事"的工程师的善意提醒。