一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

为什么Redis 4.0之后Lazy Free能缓解雪崩压力_异步删除大Key实践

时间:2026-07-16 18:19:58 编辑:袖梨 来源:一聚教程网

UNLINK能缓解雪崩压力,是因为它将内存释放移交BIO后台线程,避免主线程阻塞;即使删除2000万字段的Hash,命令本身仍毫秒级返回,真正释放由后台默默完成。

UNLINK 能缓解雪崩压力,是因为它把内存释放从主线程挪到了 BIO 后台线程,避免单次删除阻塞整个 Redis 实例。 这不是“变快了”,而是“不卡主线程了”——哪怕删的是 2000 万字段的 HashUNLINK 命令本身仍能毫秒级返回,后续清理由后台默默完成。

UNLINK 和 DEL 的底层行为差异

DEL 是同步释放:主线程遍历整个数据结构、逐个释放每个元素内存、最后才返回。遇到大 SetHash,耗时直接上秒级,期间所有请求排队等待。

UNLINK 是逻辑摘除 + 条件异步释放: - 先从 db->dictdb->expires 中摘掉 key 的引用(O(1)) - 再调用 lazyfreeGetFreeEffort(val) 算释放代价(String 为 1,HashHLENListLLEN) - 若代价 > LAZYFREE_THRESHOLD(默认 64),才丢进 BIO 队列;否则仍同步删

这意味着: - 删一个含 50 个字段的 Hash,UNLINK 和 DEL 行为几乎一样(都同步删) - 删一个含 500 万字段的 Hash,UNLINK 立刻返回,真正释放由后台线程扛住

哪些场景必须用 UNLINK 而不是 DEL

以下情况一旦用 DEL,极易触发雪崩或主从切换: - 删除已知的大 Key,比如粉丝 Set、会话 Hash、日志 Sorted Set - 批量清理前先 SCAN 出疑似大 Key,再逐个 UNLINK(别用 DEL) - 在 Lua 脚本里执行删除逻辑时,必须用 redis.call('UNLINK', key),不能写 DEL - 使用 RENAME 覆盖目标 key 时,若目标 key 是大 Key,需确保 lazyfree-lazy-server-del yes 已开启,否则隐式 DEL 仍会阻塞

配置项 lazyfree-lazy-expire 为什么建议开

过期 key 清理是被动触发的,无法由业务控制时机。如果大量带 TTL 的大 Hash 在同一秒过期,DEL 式清理可能瞬间压垮主线程。

开启 lazyfree-lazy-expire yes 后: - 过期检查仍由主线程做(轻量) - 真正的内存释放交由 BIO 线程,和 UNLINK 共享同一套异步机制 - 配合 maxmemory-policy allkeys-lfu 使用时,也要同步打开 lazyfree-lazy-eviction yes,但要注意:该配置可能导致内存释放滞后,需压测确认 used_memory_peak 是否超限

注意:lazyfree-lazy-user-del 是 Redis 6.0+ 新增配置,设为 yes 可让普通 DEL 自动降级为异步行为,但不推荐依赖它——语义混淆,且掩盖了业务中真实的大 Key 问题。

真正容易被忽略的点是:UNLINK 不是万能的,它只解决“删除动作不卡主线程”,但 BIO 线程的负载会真实上升。如果连续 UNLINK 数百个上千万级的 Set,BIO 队列积压、lazyfree_objects 持续上涨,可能拖慢其他后台任务(如 AOF rewrite、RDB save)。观察 INFO memory | grep lazyfree 里的 lazyfree_pending_objects 值,超过 1000 就该预警了。

热门栏目