Redis数据删除与淘汰策略从原理到实战指南

 更新时间:2026年04月01日 10:26:29   作者:皙然  
本文讲解了Redis的数据删除与淘汰策略,从基础概念铺垫到策略细节拆解,再到底层原理和实战配置,重点介绍了三种删除策略(惰性删除、定期删除、主动删除)和六种常用淘汰策略(allkeys-lru、volatile-lru、allkeys-lfu、volatile-lfu等),感兴趣的朋友跟随小编一起看看吧

Redis 作为高性能的内存数据库,所有数据都存储在内存中,而内存资源是有限的——这就引出了两个核心问题:过期数据如何删除?内存满了之后新数据如何存储?

这两个问题分别对应 Redis 的「数据删除策略」和「数据淘汰策略」,二者相辅相成,共同决定了 Redis 的性能、内存利用率和数据一致性。很多开发者在使用 Redis 时,容易混淆这两个概念,甚至因配置不当导致内存溢出、数据丢失或性能瓶颈。

本篇博客将从「基础概念铺垫」到「策略细节拆解」,再到「底层原理」和「实战配置」,把 Redis 数据删除与淘汰策略讲透,无论是面试备考还是生产实践,都能直接套用。

一、前置基础:先搞懂2个核心前提

在讲解具体策略前,必须先明确两个基础概念,否则容易理解偏差:

1. 过期数据 vs 非过期数据

Redis 支持给 key 设置过期时间(通过 EXPIRE、PEXPIRE 等命令),过期数据是指「到达预设过期时间但尚未被删除的 key」;非过期数据则是没有设置过期时间,或未到达过期时间的 key。

注意:过期数据不一定会被立即删除,Redis 不会实时监控每一个 key 的过期状态(否则会消耗大量CPU),而是通过特定策略“懒”删除或“批量”删除。

2. 数据删除 vs 数据淘汰

这是最容易混淆的两个概念,一句话区分:

  • 数据删除:针对「过期数据」的清理操作,核心是“删除过期的key”,释放内存;
  • 数据淘汰:针对「内存满了之后」的处理操作,核心是“删除部分非过期数据”,为新数据腾出内存(只有当内存达到 maxmemory 阈值时才会触发)。

简单说:删除是“清理过期垃圾”,淘汰是“内存不够时腾地方”。

二、Redis 数据删除策略(清理过期数据)

Redis 没有采用“实时删除”(每一个 key 过期就立即删除),因为实时删除会导致 CPU 利用率飙升(尤其是过期 key 极多的场景),影响 Redis 核心读写性能。

实际上,Redis 采用「三种删除策略结合」的方式,兼顾 CPU 性能和内存利用率,分别是:惰性删除、定期删除、主动删除

1. 惰性删除(Lazy Expiration):最“懒”的删除,按需触发

核心逻辑

Redis 不主动监控 key 的过期时间,只有当「用户主动访问某个 key」时,才会检查该 key 是否过期:

  • 如果 key 未过期:正常返回数据;
  • 如果 key 已过期:立即删除该 key,返回 null(或不存在)。

优点

极致节省 CPU 资源:只在“访问时”才检查过期,不占用额外的 CPU 时间,对 Redis 核心读写性能几乎无影响。

缺点

内存浪费严重:如果一个过期 key 长期不被访问,它会一直占用内存,直到被访问时才会被删除。极端情况下,大量过期 key 堆积会导致内存溢出(这也是为什么需要配合其他删除策略)。

举个例子:设置 100 万个 key,过期时间为 1 小时,1 小时后所有 key 都过期,但如果没人访问这些 key,它们会一直占用内存,直到被定期删除或主动删除清理。

2. 定期删除(Periodic Expiration):折中方案,批量检查

核心逻辑

Redis 会每隔一段时间(默认 100ms,可通过配置调整),随机抽取一部分过期 key 进行检查,如果发现过期,就删除它们。具体流程:

  • 每次执行定期删除时,从过期字典(存储所有过期 key 的字典)中随机抽取 N 个 key;
  • 检查这些 key 是否过期,删除所有过期的 key;
  • 如果删除的 key 数量超过 N 的 25%,则重复步骤 1(说明当前过期 key 较多,需要继续清理);否则结束本次定期删除。

关键配置

定期删除的频率由配置 hz 控制(默认 hz=10),hz 的值表示「Redis 每秒执行定期任务的次数」:

  • hz 值越大,定期删除越频繁,过期 key 清理越及时,但 CPU 占用越高;
  • hz 值越小,CPU 占用越低,但过期 key 清理越慢,内存浪费越严重。

生产环境建议:hz 保持默认 10 即可,若内存压力较大,可调整为 20(需注意 CPU 负载)。

优点

折中了 CPU 和内存:既不会像惰性删除那样浪费大量内存,也不会像实时删除那样占用过多 CPU。

缺点

存在“漏删”风险:因为是随机抽取检查,可能有部分过期 key 一直未被抽取到,从而长期占用内存(但可以通过惰性删除弥补:只要用户访问,就会被删除)。

3. 主动删除(Active Expiration):内存不足时的强制清理

核心逻辑

当 Redis 内存使用达到 maxmemory(最大内存阈值)时,会触发「主动删除」——优先删除过期 key,释放内存,避免内存溢出。

注意:主动删除是「淘汰策略的前置步骤」:当内存满时,Redis 会先尝试删除所有过期 key;如果删除完所有过期 key 后,内存仍然不足,才会执行「数据淘汰策略」(删除非过期 key)。

触发条件

只有当内存使用量 ≥ maxmemory 时,才会触发主动删除;如果内存未达到阈值,即使有大量过期 key,也只会通过惰性删除和定期删除清理。

总结:三种删除策略的协同工作

Redis 不是单一使用某一种删除策略,而是三者结合:

  • 日常情况下,通过「惰性删除」保证 CPU 高效,避免不必要的检查;
  • 每隔一段时间,通过「定期删除」批量清理部分过期 key,减少内存浪费;
  • 当内存不足时,通过「主动删除」优先清理所有过期 key,为新数据腾出空间;
  • 若主动删除后内存仍不足,则执行「数据淘汰策略」。

三、Redis 数据淘汰策略(内存满时腾空间)

当 Redis 内存使用达到 maxmemory,且删除所有过期 key 后内存仍然不足时,就会触发「数据淘汰策略」——删除部分非过期 key,为新数据腾出内存。

Redis 提供了 8 种淘汰策略(Redis 6.0+ 版本),其中常用的有 6 种,可分为「三类」:按访问频率淘汰、按时间淘汰、按随机淘汰。

先明确:淘汰策略的核心前提

  • 淘汰范围:默认只淘汰「设置了过期时间的 key」;若所有设置过期时间的 key 都被淘汰完,内存仍不足,则会淘汰「未设置过期时间的 key」(除非配置了只淘汰过期 key)。
  • 触发时机:每次执行「写操作」(set、hset、lpush 等)时,都会检查内存是否达到 maxmemory;若达到,则执行淘汰策略,直到内存低于 maxmemory,再执行写操作。
  • 核心配置:通过 maxmemory-policy 配置淘汰策略(默认策略:noeviction)。

8种淘汰策略详解(按常用程度排序)

先给出所有策略的对照表,再逐一拆解常用策略:

淘汰策略(配置值)

核心逻辑

适用场景

是否常用

allkeys-lru

淘汰所有 key 中「最近最少使用」的 key(LRU:Least Recently Used)

通用场景,大多数业务(如缓存、会话存储)

✅ 非常常用

volatile-lru

只淘汰「设置了过期时间」的 key 中,最近最少使用的 key

需要保留未过期 key(如核心配置),只淘汰临时缓存

✅ 常用

allkeys-random

随机淘汰所有 key 中的任意一个

对 key 访问频率无要求,追求简单高效

❌ 不常用

volatile-random

只随机淘汰「设置了过期时间」的 key

同上,且需要保留未过期 key

❌ 不常用

volatile-ttl

只淘汰「设置了过期时间」的 key 中,剩余过期时间最短(ttl 最小)的 key

希望尽快淘汰即将过期的临时缓存

⚠️ 场景化常用

volatile-lfu

只淘汰「设置了过期时间」的 key 中,最不经常使用的 key(LFU:Least Frequently Used)

key 访问频率差异大,优先保留高频访问 key

✅ 常用(Redis 4.0+ 支持)

allkeys-lfu

淘汰所有 key 中,最不经常使用的 key

通用场景,比 LRU 更精准(优先淘汰低频访问 key)

✅ 常用(Redis 4.0+ 支持)

noeviction(默认)

不淘汰任何 key,拒绝所有写操作,返回错误(读操作正常)

不允许数据丢失的场景(如核心业务数据存储)

⚠️ 特殊场景使用

重点拆解:常用策略的核心区别

日常开发中,最常用的是 allkeys-lru、volatile-lru、allkeys-lfu、volatile-lfu,这四个策略的核心区别的是「淘汰范围」和「淘汰依据」:

1. LRU vs LFU:淘汰依据的区别

  • LRU(最近最少使用):判断标准是「最后一次访问时间」—— 很久没被访问的 key,优先淘汰。
  • LFU(最不经常使用):判断标准是「一段时间内的访问次数」—— 访问频率最低的 key,优先淘汰。

举个例子:

  • keyA:每天访问 1 次,但每次访问都是最近 1 小时内;
  • keyB:每天访问 100 次,但最后一次访问是 3 天前。

LRU 会淘汰 keyB(最近最少访问),LFU 会淘汰 keyA(访问频率最低)—— 可见 LFU 更适合「访问频率差异大」的场景,能更好地保留高频访问的核心缓存。

2. allkeys vs volatile:淘汰范围的区别

  • allkeys-*:淘汰范围是「所有 key」(无论是否设置过期时间),适合「所有数据都是缓存」的场景(如商品缓存、接口缓存)。
  • volatile-*:淘汰范围是「只设置了过期时间的 key」,适合「有核心数据(未设置过期时间)和临时缓存(设置过期时间)」的场景(如核心配置 key 不设置过期,临时会话 key 设置过期)。

淘汰策略的底层实现(简化版)

很多人好奇:Redis 是如何记录 key 的访问时间/频率,实现 LRU/LFU 淘汰的?这里给出简化版原理,不用深入源码,理解即可:

  • 对于 LRU:Redis 给每个 key 维护一个「最后访问时间戳」,淘汰时,遍历候选 key(根据淘汰范围),筛选出时间戳最小(最近最少访问)的 key 进行删除。
  • 对于 LFU:Redis 给每个 key 维护一个「访问计数器」,每次访问 key 时,计数器加 1;每隔一段时间,计数器会衰减(避免旧的高频 key 一直占用),淘汰时,筛选出计数器最小(最不经常使用)的 key 进行删除。

注意:Redis 的 LRU/LFU 并非「严格意义上的全量排序」(全量排序会消耗大量 CPU),而是通过「采样排序」实现——每次淘汰时,随机抽取一定数量的 key(默认 5 个,可通过 maxmemory-samples 配置),在采样的 key 中选择最该淘汰的,兼顾性能和准确性。

四、核心配置实战(生产环境必看)

了解了删除和淘汰策略后,最关键的是「生产环境如何配置」,避免内存溢出或数据异常。以下是核心配置项和推荐配置:

1. 核心配置项说明

配置项

作用

推荐值

maxmemory

设置 Redis 最大可用内存(必须配置,否则内存会无限增长,导致服务器内存溢出)

根据服务器内存配置,建议设置为服务器内存的 50%-70%(如 8G 内存,设置为 4G)

maxmemory-policy

设置数据淘汰策略

通用场景:allkeys-lfu;有核心未过期 key:volatile-lfu

hz

定期删除的频率(每秒执行次数)

默认 10,内存压力大时可调整为 20

maxmemory-samples

LRU/LFU 淘汰时的采样数量

默认 5,采样数量越多,淘汰越精准,但 CPU 占用越高(建议保持默认)

2. 推荐配置示例(redis.conf)

# 设置最大内存为 4G
maxmemory 4gb
# 淘汰策略:所有 key 中最不经常使用的
maxmemory-policy allkeys-lfu
# 定期删除频率:每秒 10 次
hz 10
# LFU 采样数量:5 个
maxmemory-samples 5

3. 动态调整配置(无需重启Redis)

生产环境中,若需临时调整配置,可通过 Redis 命令动态修改(重启后失效,需同步修改 redis.conf 永久生效):

# 动态设置最大内存为 4G
config set maxmemory 4gb
# 动态设置淘汰策略为 allkeys-lfu
config set maxmemory-policy allkeys-lfu
# 查看当前所有配置
config get *

五、常见问题与避坑指南

在使用 Redis 数据删除与淘汰策略时,很多开发者会遇到以下问题,提前规避能少走很多弯路:

1. 问题1:内存满了,Redis 拒绝写操作(返回 OOM command not allowed when used memory > 'maxmemory')

原因:淘汰策略设置为默认的 noeviction,内存满时不淘汰任何 key,拒绝所有写操作。

解决方案:将淘汰策略修改为 allkeys-lfu 或 volatile-lfu,同时检查 maxmemory 是否配置合理。

2. 问题2:大量过期 key 堆积,内存占用过高

原因:定期删除频率过低(hz 太小),且过期 key 长期不被访问(惰性删除无法触发)。

解决方案:适当提高 hz 值(如调整为 20),同时在业务层定期清理过期 key(如通过定时任务执行 DEL 命令)。

3. 问题3:核心 key 被淘汰

原因:淘汰策略设置为 allkeys-*,核心 key 未设置过期时间,但内存满时被淘汰;或核心 key 设置了过期时间,被 volatile-* 策略淘汰。

解决方案:核心 key 不设置过期时间,淘汰策略使用 volatile-lfu(只淘汰设置了过期时间的临时 key)。

4. 问题4:LRU 淘汰策略不精准

原因:maxmemory-samples 采样数量太少,导致筛选出的“最近最少使用”key 不是真正的低频 key。

解决方案:适当提高 maxmemory-samples(如调整为 10),但需注意 CPU 负载。

六、总结

Redis 数据删除与淘汰策略,核心是「平衡 CPU 性能、内存利用率和数据一致性」,记住以下核心要点,就能轻松应对生产场景:

  • 「删除策略」是清理过期 key,三种结合:惰性删除(省 CPU)+ 定期删除(折中)+ 主动删除(内存不足时);
  • 「淘汰策略」是内存满时腾空间,常用 allkeys-lfu(通用)和 volatile-lfu(有核心 key);
  • 生产环境必须配置 maxmemory 和 maxmemory-policy,避免内存溢出;
  • LRU 看“最近访问时间”,LFU 看“访问频率”,根据业务场景选择;
  • 核心 key 不设置过期时间,避免被淘汰。

理解了这些策略,不仅能解决 Redis 内存相关的问题,还能在面试中从容应对相关问题(Redis 淘汰策略是后端面试高频题)。

如果需要,我还可以为你补充:

  • LRU/LFU 底层源码简化解析;
  • 过期 key 清理的监控方法;
  • 不同业务场景(缓存、会话、配置存储)的具体策略配置。

到此这篇关于Redis数据删除与淘汰策略从原理到实战指南的文章就介绍到这了,更多相关Redis数据删除与淘汰策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Redis实现分布式锁详解

    Redis实现分布式锁详解

    这篇文章主要介绍了redis如何实现分布式锁,文章中有详细的示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2023-04-04
  • 使用高斯Redis实现二级索引的方法

    使用高斯Redis实现二级索引的方法

    本文介绍了如何通过高斯Redis搭建二级索引,二级索引在电商、图(hexastore)、游戏等领域具有广泛的应用场景,高斯redis现网亦有很多类似应用,需要的朋友跟随小编一起看看吧
    2022-07-07
  • Redis教程(一):Redis简介

    Redis教程(一):Redis简介

    这篇文章主要介绍了Redis教程(一):Redis简介,本文是系列文章的第一篇,欢迎大家跟随本教程学习Redis数据库,需要的朋友可以参考下
    2015-04-04
  • 基于Redis实现API接口访问次数限制

    基于Redis实现API接口访问次数限制

    日常开发中会有一个常见的需求,需要限制接口在单位时间内的访问次数,比如说某个免费的接口限制单个IP一分钟内只能访问5次,该怎么实现呢,本文小编给大家介绍了如何基于Redis实现API接口访问次数限制,需要的朋友可以参考下
    2024-11-11
  • mac下redis安装、设置、启动停止方法详解

    mac下redis安装、设置、启动停止方法详解

    这篇文章主要介绍了mac下redis安装、设置、启动停止方法详解,需要的朋友可以参考下
    2020-02-02
  • 详解Redis 键和字符串常用命令

    详解Redis 键和字符串常用命令

    字符串是 Redis 最基本的数据结构,它将以一个键 和一个值 储存在 Redis 内部,本文重点给大家介绍Redis键和字符串常用命令,感兴趣的朋友一起看看吧
    2022-02-02
  • redis中5种数据基础查询命令

    redis中5种数据基础查询命令

    本文主要介绍了redis中5种数据基础查询命令,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • redis常用命令整理

    redis常用命令整理

    在本篇文章里小编给大家整理的是关于redis常用命令整理相关内容需要的朋友们可以学习下。
    2020-03-03
  • redis中hash表内容删除的方法代码

    redis中hash表内容删除的方法代码

    在本篇文章里小编给各位整理了关于redis中hash表内容怎么删除的方法以及技巧代码,需要的朋友们分享下。
    2019-07-07
  • Redis实现用户签到的示例代码

    Redis实现用户签到的示例代码

    Redis的位图可以高效实现用户签到功能,每个bit位对应一个签到状态,节省存储空间,利用SETBIT、GETBIT等命令操作签到数据,可统计连续签到天数和本月签到情况,感兴趣的可以了解一下
    2024-09-09

最新评论