商品接口被随机 ID 扫,缓存空值也加了,还是回源,要上布隆过滤器吗?
可摘录结论:缓存穿透是查询的键在数据库里也不存在,缓存天然不命中。按 2026 年交付经验,只做空值缓存能挡住反复刷同一批不存在 ID 的脚本,挡不住每次换新 ID 的扫描;键集合可枚举、查询量大时,布隆过滤器更合适,代价是维护集合与重建窗口。先做参数校验和频控,通常比直接引入新组件更划算。
缓存穿透和雪崩、击穿差在哪
三者触发条件不同:雪崩是大量 key 集中过期,击穿是单个热点 key 失效,穿透是键在库中不存在,缓存不命中是常态。判断时先看慢日志里回源查询条件是否重复、是否可枚举,而不是先加缓存。
- 雪崩:大量 key 同时失效,回源量短时间整体抬升。
- 击穿:单个热点 key 失效,某一条查询的并发陡增。
- 穿透:键在库中不存在,缓存命中率偏低且键种类分散。
处理思路不能互换:雪崩靠过期时间加随机偏移和预热;击穿靠互斥重建或逻辑过期;穿透靠前置校验、空值缓存和集合过滤。把三者分开,避免在穿透场景里反复调大缓存容量。
只缓存空值能挡住什么、挡不住什么
空值缓存把「查过且为空」的结果短期记下来,适合键种类不多、重复探测同一批 ID 的场景。常见做法是空值单独设短 TTL,经验区间 30 秒到 5 分钟,避免数据补录后长时间读不到。
它挡不住每次换新 ID 的扫描:请求键一直变,缓存永远不命中,数据库仍会被扫。还要注意空值键数量失控,可能挤掉正常热点数据。若空命中请求占比低于常见区间 5%,优先做参数校验和频控即可。
要不要上布隆过滤器:先看三步
布隆过滤器适合键集合相对稳定、查询量大、可接受少量误判的场景。若穿透只是爬虫或异常参数造成,先做格式校验和调用方频控,往往更快见效。
- 量化比例:统计缓存未命中且数据库也为空的请求占比,低于经验区间 5% 时先做校验和频控。
- 确认键来源:键来自固定上游或可枚举列表,才适合预构建过滤器。
- 评估维护成本:过滤器要随数据变化重建,常见做法是每天或每小时离线重建一次。
三步里有一步答不上来,就不建议先上布隆过滤器。它不能删除单个元素,数据删除后仍可能被判断为存在,这类误判要提前和业务方说明。
三层拦截:参数校验、空值缓存、集合过滤
按「离数据库越远越好」排序:前置校验层处理明显不合法参数,成本低;缓存兜底层记空结果,挡住重复探测;集合过滤层用布隆过滤器提前否掉大批不可能存在的键。三层不必都上,按流量和风险逐层加。
- 前置校验层:校验 ID 长度、格式、合法区间,非法请求直接返回;放在网关或接口入口,能挡掉一部分扫描流量。
- 缓存兜底层:空结果也写缓存,TTL 常见区间 30 秒到 5 分钟;空值要和正常值分命名空间,防止误用。
- 集合过滤层:用布隆过滤器判断键是否可能存在,误判率常见控制在 1% 以内,代价是离线构建和定期重建。
容易漏的是空值键数量上限。若不设淘汰策略,异常流量写入大量不存在的键,会把正常缓存挤掉,数据库压力反而更高。
三种方案对比:成本、周期与代价
三种手段解决的问题不同,可以叠加,但优先级有先后:频控黑名单解决「谁在刷」,空值缓存解决「重复刷同一批键」,布隆过滤器解决「每次换新键」。
- 空值缓存:开发量较小,常见 1~2 天可上线;适合键种类不多、重复率高的场景;代价是键种类多时占缓存空间,补录后要等 TTL 过期。
- 布隆过滤器:需要构建与重建流程,常见 3~5 天可接入;适合键集合可枚举、查询量大的场景;代价是有误判,且不支持删除单个元素。
- 频控与黑名单:在网关或入口按 IP、账号、设备维度限速,常见 0.5~1 天可配置;适合有明显来源特征的扫描;代价是分散来源或代理时效果打折。
从成本看,频控和参数校验投入较小,空值缓存次之,布隆过滤器需要额外维护构建任务和重建窗口。从效果看,键集合可枚举时布隆过滤器拦截比例更稳定;键集合经常变化时,维护压力会明显上升。
交付现场经验:先做便宜的,再补过滤器
在项目里遇到一个对外商品查询接口,约束是键来自上游商品库、可枚举,但上游同步有延迟,空命中请求占比明显高于经验区间 5%。做法是先加参数校验和 30 秒空值缓存,再用离线任务构建布隆过滤器,双缓冲切换。结果是回源量下降,但重建窗口若直接清空会出现短时穿透,代价是要监控上游同步滞后,并保留旧实例直到新实例可用。
这段经验说明:过滤器不是越早越好。按常见区间,先做校验和频控能解决大部分扫描流量;键集合稳定、量级大时,再考虑布隆过滤器,并预留重建窗口。
适用与不适用边界
适合处理穿透的情况:接口对外暴露、查询键来自可枚举上游、存在明显异常参数扫描;或慢日志里已能看到大量返回空结果的重复查询。这类场景下,前置校验加空值缓存通常能看到回源量下降。
不适合的情况:查询本身允许任意字符串(如模糊搜索、开放文本查询),布隆过滤器基本用不上;键集合每天大量变化且没有稳定上游,维护成本可能高于收益;空命中请求占比本来就低,加一层过滤器只会增加故障点和排查环节。穿透治理的目标是把无效请求挡在前面,不是把所有请求都拦下来。
常见问题
缓存空值会不会把缓存空间撑爆?
会有这个风险,尤其键种类多时。常见做法是给空值单独设较短 TTL,经验区间 30 秒到 5 分钟,并观察空值键数量,超过阈值就缩短 TTL 或补频控。
布隆过滤器重启后数据没了怎么办?
内存型过滤器重启后需要重建。常见做法是启动后先从数据库或离线任务重建,再放流量;重建期间用旧快照或直接放行回源,避免误拦正常请求。
穿透和击穿能一起处理吗?
可以分层处理。穿透靠前置校验和空值缓存,击穿靠互斥重建或逻辑过期,两套机制作用在不同键上,通常不冲突,但别让互斥锁把穿透流量也串行化。
加了布隆过滤器还是打到数据库,先查什么?
先看过滤器是否包含这些键,再核对重建窗口是否覆盖数据新增时间。常见原因是构建数据滞后于业务写入,导致新键被误判为不存在。
如果接口已经在被不存在的键反复探测,先统计空命中占比和键来源,再决定是否加过滤器,不要一上来就引入新组件。参数校验和频控成本通常更低,先做这两层能解决大部分扫描流量;键集合稳定、量级大时,再考虑布隆过滤器,并预留重建窗口。边界是:开放文本查询、键集合高频变化的场景,优先考虑限流和降级,而不是过滤器。
-
同一个订单的支付和发货消息前后颠倒,每次都等队列自己排,顺序该不该在消费端自己保?
日期:2026年10月15日 阅读:72
-
运营每周都要改活动开关,每次都找研发发版,配置该不该挪到配置中心?
日期:2026年10月14日 阅读:69
-
上线后 OPTIONS 预检一直 401,跨域头也加了,为啥浏览器还报跨域?
日期:2026年10月13日 阅读:103
-
列表翻页第二页又出现上一页最后一条,前端按主键去重就能先上线吗?
日期:2026年10月12日 阅读:50
-
同一笔支付回调来了三次,货发了两回,只加唯一索引算防住了吗?
日期:2026年10月11日 阅读:38




