导读:本期聚焦于小伙伴创作的《Redis的lazyfree-lazy-eviction延迟淘汰机制到底是怎么工作的》,敬请观看详情。当Redis内存达到上限触发键淘汰时,直接同步删除大键会造成主线程卡顿。lazyfree-lazy-eviction机制把淘汰删除操作放到后台线程异步执行,避免阻塞请求。该配置针对volatile-lru、allkeys-lru等策略生效,仅影响被淘汰键的释放环节。开启后,内存回收的耗时从主线程转移到bio懒删除线程,命令延迟更稳定。但异步释放会让已淘汰键的内存不会立刻归还,需要结合maxmemory和监控观察真实占用。理解它与lazyfree-lazy-expire的区别,能帮助我们在高并发场景下合理调优。

Redis在运行期间一旦使用的内存达到maxmemory设定的阈值,就会按照配置的淘汰策略挑出部分键进行删除,为新写入的数据腾出空间。如果恰好被淘汰的是一个包含数百万个元素的哈希表或者一个超大的有序集合,同步删除会消耗大量CPU时间,这段时间内主线程无法处理任何其他命令,表现为延迟陡增甚至超时。lazyfree-lazy-eviction正是为了解决这类大键淘汰阻塞问题而引入的延迟释放开关。

Redis的lazyfree-lazy-eviction延迟淘汰机制到底是怎么工作的

lazyfree-lazy-eviction的基础原理与配置方式

在Redis 4.0之后,官方引入了惰性删除(lazy free)系列特性,其中lazyfree-lazy-eviction专门控制内存淘汰时的键释放行为。当该参数设为yes时,Redis在执行业务命令触发内存淘汰后,不会在主线程里直接调用同步释放函数,而是把待删除的键封装成任务,投递给后台的BIO_LAZY_FREE线程去真正回收底层数据结构与内存。

配置方法非常简单,可以在redis.conf中写入lazyfree-lazy-eviction yes,也可以通过命令行在运行时动态修改:config set lazyfree-lazy-eviction yes。需要注意的是,它只作用于因为内存不足而被淘汰的键,并不改变键的挑选逻辑。也就是说,无论是volatile-lru、allkeys-random还是volatile-ttl,选哪些键淘汰由策略决定,而选出来之后怎么删则由该参数决定。

从源码角度看,Redis在freeMemoryIfNeeded函数中判断若开启此选项,会调用dbAsyncDelete而不是dbSyncDelete。前者仅仅把键从字典中摘除,实际释放交给懒删除线程,因此主线程的淘汰路径非常轻量。这种解耦让单次命令的尾延迟显著降低,尤其适合缓存场景中存在大键的实例。

同步淘汰与延迟淘汰的性能差异对比

为了直观理解差异,我们假设一个哈希键big:user拥有五百万个字段,占用内存约八百兆。在同步淘汰模式下,主线程执行释放要遍历整个哈希表、逐个释放键值对节点,耗时可能达到几十毫秒甚至上百毫秒,期间所有连接命令排队。在延迟淘汰模式下,主线程瞬间完成键的字典摘除并返回,后台线程在几十毫秒后慢慢释放,用户侧几乎无感知。

我们可以用一段伪代码模拟两种路径的差异:

// 同步淘汰(lazyfree-lazy-eviction no)
public void evictSync(RedisDb db, String key) {
    // 主线程直接释放,阻塞
    HashMap<String, String> map = db.getHash(key);
    for (Entry<String, String> e : map.entrySet()) {
        freeEntry(e); // 耗时操作在主线程
    }
    db.remove(key);
}

// 延迟淘汰(lazyfree-lazy-eviction yes)
public void evictAsync(RedisDb db, String key) {
    db.remove(key); // 仅摘除
    BioLazyFree.submit(() -> {
        HashMap<String, String> map = db.getHashBackup(key);
        for (Entry<String, String> e : map.entrySet()) {
            freeEntry(e); // 后台线程释放
        }
    });
}

从监控指标上,开启延迟淘汰后,INFO stats中的lazyfree_pending_objects会显示等待后台释放的对象数,而evicted_keys仍然正常递增。若发现该待释放数值长期很高,说明淘汰速度超过后台释放能力,可能需要降低写入压力或扩容。

不过延迟淘汰并非银弹。因为内存不会立刻归还操作系统,Redis的used_memory在键被逻辑删除后可能仍显示高位,直到后台线程完成。若依赖内存水位做告警,应区分逻辑删除与物理释放,避免误判。

生产环境调优与常见误区

很多人在开启lazyfree-lazy-eviction的同时,以为所有删除都变异步了,这是错误认知。它仅覆盖内存淘汰这一特定路径,像主动执行的DEL命令默认仍是同步,除非额外开启lazyfree-lazy-user-del。另外lazyfree-lazy-expire管的是过期键删除,与淘汰互不替代,高并发实例建议三者按业务分别评估。

在容器化部署中,若设置了内存上限为容器limit的百分之八十,开启延迟淘汰可防止OOM Killer因瞬时淘汰卡顿导致健康检查失败。但应配合maxmemory-policy合理选择,比如用allkeys-lru时大键容易被选中,此时延迟淘汰收益最大;若用volatile-ttl且大键无过期时间,则不会被淘汰,参数无意义。

最后给出一个实用的配置检查脚本思路:定期拉取config get lazyfree-lazy-evictioninfo memory,当mem_fragmentation_ratio异常且lazyfree_pending_objects持续增长时,记录日志并提醒调优。这样可以在保障低延迟的同时,掌握真实内存回收节奏,让Redis在重淘汰负载下依然平稳。

Redislazyfree-lazy-evictionlazy_free修改时间:2026-08-16 09:48:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。