Redis 7.2 中启用 lazyfree-lazy-eviction 可缓解大 key 淘汰阻塞,但需配合 allkeys-lru 等可删型淘汰策略,并用 UNLINK 替代 DEL;单独开启无效,且需关注 used_memory_rss 与内存碎片率。

Redis 7.2 中启用 lazyfree 能显著降低大 key 淘汰时的主线程阻塞,但必须配合正确的淘汰策略和参数组合才生效;单独开 lazyfree 不解决内存满时的卡顿。
lazyfree-lazy-eviction 必须显式开启
Redis 默认关闭所有 lazyfree 场景,lazyfree-lazy-eviction 控制“内存淘汰时是否异步释放”,它和 maxmemory-policy 联动——只有当淘汰策略触发实际删除(如 volatile-lru 或 allkeys-lfu)且选中了某个 key,这个配置才起作用。若策略是 noeviction,该配置完全不生效。
- 在
redis.conf中设置:lazyfree-lazy-eviction yes - 运行时动态启用:
CONFIG SET lazyfree-lazy-eviction yes - 确认是否生效:
CONFIG GET lazyfree-lazy-eviction返回yes - 注意:该配置仅影响
evict流程中的 value 释放,key 的 dict 删除仍同步,但已足够缓解 90% 以上的阻塞
淘汰策略必须选“可删型”,且避免 volatile-ttl
volatile-ttl 策略本身不删除 key,只按过期时间排序,真正删 key 还得靠过期删除机制(惰性+定期),它不走 evict 路径,因此完全绕过 lazyfree-lazy-eviction。要让 lazyfree 在内存压力下起效,必须用明确会触发删除动作的策略:
- 推荐:
allkeys-lru、allkeys-lfu、volatile-lru、volatile-lfu - 禁用:
noeviction(不删)、volatile-ttl(不在此路径删) - 验证当前策略:
CONFIG GET maxmemory-policy - 修改后需观察
INFO stats中的evicted_keys是否增长,而非仅看expired_keys
大 key 淘汰前先用 unlink 替代 del
即使 lazyfree-lazy-eviction 开启,如果业务代码里手动执行 DEL bigkey,仍会同步阻塞。Redis 7.2 支持 UNLINK 命令,它把 key 从数据库中摘除后,立即返回,释放 value 的操作交给后台线程处理——这和 lazyfree 的底层机制一致。
- 替换所有可能操作大 key 的
DEL为UNLINK - 客户端 SDK(如 Lettuce、Jedis)需确认是否默认支持
UNLINK;旧版 Jedis 可能需升级或手动调用 -
UNLINK对不存在的 key 返回 0,行为与DEL一致,迁移成本低 - 注意:
UNLINK不影响事务(MULTI/EXEC内仍为同步DEL)
别忽略 used_memory_rss 和内存碎片率
开了 lazyfree 后,used_memory 下降快,但 used_memory_rss 可能滞后——因为后台线程释放内存页需要时间,且 glibc 内存分配器未必立刻归还 OS。此时若监控只看 used_memory,容易误判内存已释放。
- 关键指标组合:
used_memory+used_memory_rss+mem_fragmentation_ratio -
mem_fragmentation_ratio > 1.5且used_memory_rss - used_memory > 1GB时,说明有大量内存未归还,需关注INFO memory中的allocator_active/allocator_resident - 此时
MEMORY PURGE(Redis 7.0+)可强制 glibc 归还内存,但会短暂阻塞,建议在低峰执行
lazyfree 不是银弹:它把同步删除转成后台任务,但后台线程负载过高或内存碎片严重时,释放延迟依然存在。真正压测时,要同时看 evicted_keys 增速、lazyfree_pending_objects 和 used_memory_rss 变化节奏,三者脱节就说明释放链路某环卡住了。











