SQL缓存穿透与雪崩处理_缓存保护策略

7次阅读

sql 缓存穿透和雪崩是应用层缓存策略不当导致的数据库风险:穿透因查不存在数据反复打库,可用布隆过滤器、空值缓存和限流防控;雪崩因缓存集中失效引发流量洪峰,需加随机过期时间、多级缓存及永不过期 + 异步刷新;同时须加固 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 阈值控制),超限直接降级返回默认数据。
text=ZqhQzanResources