缓存空值需设合理TTL(5–30分钟),依赖Redis过期机制自动清理,禁用KEYS批量删key,异常时用SCAN+ TTL过滤删除永不过期key。

缓存空值的Key会越积越多,不清理会撑爆内存
缓存空值(如 NULL、"NULL" 或自定义 NullValue 对象)是防穿透最常用手段,但它有个硬伤:无效 key 持续写入,TTL 一过就自动消失——可如果 TTL 设得太长(比如 24 小时),或业务中大量 ID 永远不会被访问(如已下线的商品、注销的用户),这些空值 key 就会长期滞留,占用 Redis 内存,最终触发 maxmemory 策略淘汰,甚至影响有效数据命中率。
Redis 自带的过期机制就是清理主力,别自己扫库删key
绝大多数场景下,**不需要、也不该手动遍历删除空值 key**。Redis 的过期机制(EXPIRE/SETEX)本身已是可靠清理器,关键在 TTL 设置是否合理:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
setex或set命令带EX参数写入空值时,必须指定明确的过期时间(如300秒),不能设为永不过期 - TTL 建议控制在
5–30 分钟:太短(如 60 秒)会导致高频无效请求仍反复穿透;太长(如 2 小时+)会让冷空值堆积 - 避免用
SET+ 后续EXPIRE两步操作,防止中间失败导致 key 永久残留;优先用原子命令如SETEX - 监控
used_memory和expired_keys指标,若发现expired_keys增速远低于预期,说明部分空值未设 TTL 或被覆盖
真要批量清理?用 SCAN + TTL 过滤,避开 KEYS
只有当出现异常情况(如上线初期误配了长 TTL、或某次批量导入导致数万空值 key 全部设成 7 天过期),才需人工干预。此时绝不能用 KEYS ——它会阻塞 Redis 主线程:
- 改用
SCAN游标式遍历,配合TTL命令判断剩余过期时间,只对TTL返回-1(永不过期)或-2(已过期但未被惰性删除)的 key 执行DEL - 示例命令片段:
redis-cli --scan --pattern "user:id:*" | while read key; do<br> ttl=$(redis-cli ttl "$key")<br> if [ "$ttl" = "-1" ]; then redis-cli del "$key"; fi<br>done
- 生产环境执行前,务必限制 QPS(加
sleep 0.01)、避开高峰,并在从节点验证逻辑 - 更稳妥的做法是:在应用层写空值时统一加命名空间前缀(如
empty:user:id:),后续用SCAN限定 pattern,避免误删
布隆过滤器重建时,旧过滤器残留不影响空值清理
如果用了布隆过滤器(BloomFilter),它本身不存储 key,只做存在性判断;即使旧过滤器未及时清理(比如重建后老 filter 还在内存里),也不会导致空值 key 积压——因为布隆过滤器不写 Redis,空值 key 的生命周期仍由你写的 SETEX TTL 控制。真正要注意的是:布隆过滤器重建后,新插入的合法 key 必须同步进新 filter,否则新请求会被误判为“不存在”,反而加剧空值写入。

















