sql缓存穿透和雪崩是应用层缓存策略不当导致的数据库风险:穿透因查不存在数据反复打库,可用布隆过滤器、空值缓存和限流防控;雪崩因缓存集中失效引发流量洪峰,需加随机过期时间、多级缓存及永不过期+异步刷新;同时须加固sql层防护。

SQL缓存穿透和雪崩不是数据库自身的机制问题,而是应用层使用缓存(如Redis)保护MySQL等SQL数据库时,因策略不当引发的典型风险。核心在于:缓存没拦住请求,导致大量流量直击SQL层,压垮数据库。
缓存穿透:查不存在的数据,反复打库
典型场景是攻击者用随机ID(如 user_id=9999999、-1、abc)高频请求,缓存不命中、数据库也查不到,但每次都要走一遍SQL查询。久而久之,数据库连接被打满,慢查询堆积,甚至宕机。
- 布隆过滤器前置拦截:系统启动时,把所有合法主键(如用户表id、商品表sku_id)加载进布隆过滤器;请求来时先过滤——若布隆判定“一定不存在”,直接返回404,连缓存和SQL都不触达。
- 空值缓存+短过期:对确认不存在的key(如SELECT * FROM users WHERE id=9999999 → 0 rows),仍往缓存写入一个标记值(如NULL或"MISS"),并设5–60秒过期。避免同一无效key反复穿透。
- 配合限流与监控:对单IP/单用户单位时间内的空响应请求计数,超阈值自动限流(如令牌桶);同时告警“空命中率>30%”,辅助识别穿透行为。
缓存雪崩:大批缓存集中失效,SQL瞬间承压
常见于批量设置相同TTL(如凌晨2点统一刷新,所有热点商品缓存设为2小时后过期),结果整点一到,成千上万key同时失效,请求洪水般涌向MySQL。
- 过期时间加随机扰动:基础过期时间(如7200秒)基础上,叠加0–600秒随机值。例如:expire = 7200 + random(0, 600)。让失效分散在10分钟窗口内,削平峰值。
- 多级缓存 + 本地缓存兜底:在Redis之上加一层Caffeine或Guava本地缓存(带短TTL),即使Redis集群短暂不可用,本地缓存仍可抗几秒流量,为恢复争取时间。
- 核心数据永不过期 + 异步刷新:对关键数据(如配置表、城市列表),缓存不设expire,改用后台定时任务或MQ监听DB变更,主动更新缓存内容,彻底规避失效风险。
别漏掉SQL层本身的防护
缓存只是第一道防线,SQL层需同步加固:
- MySQL开启slow_query_log,阈值设为100ms,快速定位穿透引发的慢SQL;
- 配置max_connections合理上限,配合连接池(如HikariCP)复用连接,防连接耗尽;
- 对高频查询字段建好覆盖索引,避免穿透请求触发全表扫描;
- 必要时在SQL前加轻量熔断(如Sentinel QPS阈值控制),超限直接降级返回默认数据。










