布隆过滤器必须在请求入口处第一时间拦截,即“请求→布隆过滤器判断→存在才查缓存/db,不存在直接返回”,绝不能置于缓存或数据库查询之后;初始化需全量加载合法key,误判率建议设为0.01,须与空值缓存、参数校验协同分层防御。

布隆过滤器必须在查询前拦截,不能查完再判断
布隆过滤器不是用来“验证缓存结果”的,而是请求刚进来时就做的第一道筛子。如果等 GET 缓存失败、再查数据库、最后才用布隆过滤器,那就完全失去了意义——无效请求已经打到数据库了。
典型错误写法是把布隆过滤器放在数据库查询之后,误以为它能“补救”穿透;正确顺序只能是:请求 → 布隆过滤器判断 → 存在则走缓存/DB流程,不存在则直接返回。
- 初始化阶段要把所有合法
key(如用户ID、商品ID)一次性加载进布隆过滤器,不能漏加或延迟加 - 布隆过滤器不支持删除,所以数据库删数据后,该
key在过滤器里仍显示“可能存在”,需靠定期重建或双过滤器切换来保证准确性 - 误判率建议设为
0.01(1%),太高会漏拦,太低会显著增加内存占用;1亿个key对应约 12MB 内存
空值缓存要带明确标记,且 TTL 必须足够短
缓存 "NULL" 或 "" 不是目的,目的是让相同无效请求不再穿透。但若没加标记或过期时间太长,会污染缓存、挤占内存,甚至掩盖真实业务空值逻辑。
比如用 SET shop:999999 "" EX 300 缓存空值,后续代码必须显式判断这个空字符串是否代表“查无此物”,而不是当成正常数据反序列化。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 推荐用固定标记如
"@NULL@",避免和业务中可能存在的真实空字符串混淆 -
TTL建议控制在60~300秒之间;超过 5 分钟,攻击者用不同随机key扫描仍可能填满 Redis 内存 - 不要对所有空结果无差别缓存——前端传参明显非法(如
id=-1)应由接口层直接拦截,不进缓存逻辑
参数校验是成本最低的防线,但常被跳过
很多团队一上来就堆布隆过滤器或空值缓存,却忘了在 Controller 层用几行代码做基础校验。其实 id ≤ 0、len(username) > 32、!id.matches("^\d+$") 这类检查能挡住 80% 的低级穿透请求,且零额外资源消耗。
- 校验必须在任何缓存操作之前执行,否则无效请求仍会触发
GET和SET操作 - 不要只校验格式,要结合业务范围:比如订单号前缀必须是
"ORD",分类 ID 只能是1~20 - Spring Boot 中可用
@Valid+ 自定义ConstraintValidator统一处理,避免散落在各 Service 方法里
布隆过滤器和空值缓存不是二选一,而是分层配合
单独用布隆过滤器扛不住“格式合法但业务不存在”的请求(比如一个真实存在的用户ID,但该用户已被注销);单独用空值缓存又防不住海量不同 key 的扫描攻击。两者必须协同:
布隆过滤器负责筛掉“绝对不存在”的请求(如 user:abc、shop:-1),空值缓存负责兜底“曾经存在但已删除”的请求(如 user:1001 已注销)。
- 布隆过滤器拦截失败(即返回“可能存在”)时,才进入缓存查询流程
- 缓存未命中 → 查 DB → 若 DB 也为空 → 写入带标记的空值缓存,TTL 设短
- 注意:布隆过滤器重建期间,要保留旧实例继续服务,新实例加载完成后再原子切换,否则会出现拦截真空期










