SQL缓存穿透防护_缓存空值与限流策略

2次阅读

缓存穿透指查询根本不存在的数据导致请求直击数据库,防护需三管齐下:缓存空值(用占位符+1–3分钟过期)、请求限流(按key/IP分层控制)、布隆过滤器(前置存在性校验,支持增量更新),并辅以监控告警。

SQL缓存穿透防护_缓存空值与限流策略

缓存穿透是指查询一个**根本不存在的数据**,导致请求绕过缓存直接打到数据库,当这类请求量大时,可能压垮数据库。常见于恶意攻击或用户输入非法ID(如负数、超长字符串、明显不存在的ID)等场景。防护核心是:不让无效请求穿透到DB,同时避免缓存被“污染”或限流策略误伤正常流量。

缓存空值:堵住“查不到”的缺口

对确认不存在的数据(如数据库select返回NULL),也写入缓存,但设置较短的过期时间(如1–5分钟),并标记为“空值”。下次相同请求直接命中缓存,不查库。

  • 注意空值标识:不要简单存null或空对象,建议统一用特定占位符(如“NULL_OBJ”)或封装空响应结构,防止反序列化失败或业务误判
  • 过期时间要合理:太短起不到防护作用;太长可能掩盖真实数据上架(比如新商品刚发布)。推荐1–3分钟,配合布隆过滤器可适当延长
  • 需配合唯一键校验:确保空值只针对合法格式的key缓存(例如ID为正整数),非法格式(如”abc”、”-1″)应前置拦截,不进缓存逻辑

请求限流:给穿透流量装上“闸门”

单个key高频查询空值,大概率是攻击或异常行为。可在应用层或网关层对同一key(或同一用户/IP)做QPS限制。

  • 按key限流:例如redis + lua脚本实现“1分钟内同一key最多访问5次”,超限直接返回错误或默认值,不查缓存也不查库
  • 分层限流更稳妥:先在API网关限制全局/用户级QPS,再在服务内对可疑key做细粒度控制,避免单点打爆
  • 区分限流动作:对已知空值key限流可返回“暂无数据”;对非法key(如非数字ID)建议直接400拦截,不计入限流窗口

布隆过滤器:前置“存在性检查”

在缓存之前加一层概率型数据结构,快速判断某key“一定不存在”或“可能存在”。它不存真实数据,内存占用极小,适合亿级ID白名单场景(如已上架商品ID集合)。

  • 初始化需全量加载:启动时从DB或持久化存储加载所有有效key构建布隆过滤器;支持定期增量更新(如监听binlog同步新增ID)
  • 有误判率但不漏判:可能出现“不存在的key被判定为存在”(假阳性),此时请求照常走缓存→DB流程,不影响正确性;但绝不会把存在的key判成不存在(真阴性保障)
  • 不适合动态变化频繁的场景:如果有效key每秒新增数千,布隆过滤器重建成本高,此时优先依赖空值缓存+限流组合

监控与兜底:让防护看得见、控得住

再好的策略也需要可观测性支撑。必须记录三类关键指标:

  • 空值缓存命中率:突然升高可能说明出现批量无效查询(如爬虫试ID)
  • 限流触发次数及key分布:定位高频恶意key,便于人工拉黑或调整策略
  • DB空查询量(WHERE id = ? 返回0行):该数值应趋近于0,否则说明防护链路某环失效

建议配置告警:空值缓存命中率连续5分钟 > 30%,或单个key限流触发超100次/分钟,立即通知负责人核查。

text=ZqhQzanResources