空值缓存会放大带宽消耗,因其强制每次无效请求都走完整tcp链路,恶意大量随机key导致redis处理海量小包、带宽被无效流量占满;布隆过滤器必须前置在redis之前拦截“绝对不存在”的请求,否则无效;空值缓存仅对高频重复无效key有效,需配合格式校验、频次限制和极短value;本地缓存应作为第一道防线拦截重复无效key,减少网络请求。

为什么空值缓存会放大带宽消耗
很多人以为缓存空值(SET user:999999 "NULL" EX 60)只是占点内存,其实它会显著增加 Redis 实例的网络带宽压力。每次空值读取都要走一次完整的 TCP 请求/响应链路,而恶意请求往往携带大量不同 key(如 user:123456789、user:123456790…),导致 Redis 持续处理海量小包请求——带宽被无效流量吃满,甚至触发内核 tcp_mem 阈值告警。
布隆过滤器必须前置在 Redis 之前
布隆过滤器本身不产生 Redis 网络调用,但它的部署位置决定是否真能省带宽。常见错误是把布隆过滤器放在应用层查完 Redis 之后再用,这毫无意义;正确做法是:所有请求先过布隆过滤器,命中“绝对不存在”就直接返回 404,连 Redis 连接都不建。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 使用
guava或redisbloom模块时,确保初始化阶段将全量合法 key(如用户 ID、商品 SKU)一次性加载进过滤器,而不是运行时动态写入 - 若业务有删数据场景,布隆过滤器无法删除元素,必须配合定时重建(如每天凌晨用最新主键集生成新 filter,双 buffer 切换)
- 误判率设为
0.01(1%)时,1 亿 key 占用约 1.2GB 内存;设为0.001(0.1%)则翻倍,需权衡带宽节省 vs 内存开销
空值缓存只对高频重复无效 key 有效
如果攻击者每秒生成 10 万个随机 key(如 order:abc123、order:def456…),缓存空值反而让 Redis 变成“无效 key 垃圾桶”,既耗内存又增带宽。这时空值策略应加条件:
- 只对符合业务格式的 key 缓存空值(例如
user:\d{10}才允许写SET,其他非法格式直接拦截) - 用
INCR+EXPIRE组合做请求频次统计,单个 key 5 秒内超 3 次未命中才写空值,避免被扫库式请求拖垮 - 空值 value 统一用极短字符串(如
""或"-"),别用 JSON 或长标记,减少序列化/传输体积
本地缓存要拦住第一波无效请求
Redis 带宽消耗本质是“请求到达 Redis 进程”才开始计算。在应用进程内加一层轻量本地缓存(如 Caffeine 的 CacheLoader),能直接拦截大部分重复无效 key,根本不会发网络请求。
- 配置
maximumSize(10000)+expireAfterWrite(1, TimeUnit.MINUTES),足够覆盖常见无效 key 的重试窗口 - 本地缓存的 key 判定逻辑必须和布隆过滤器一致(例如都用相同哈希函数),避免出现“本地说存在,布隆说不存在”的冲突
- 注意 JVM 堆内存水位,别让本地缓存无限制增长,建议开启
recordStats()监控 hit/miss ratio










