当前位置: 代码网 > it编程>数据库>Redis > Redis数据删除与淘汰策略从原理到实战指南

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

2026年04月01日 Redis 我要评论
redis 作为高性能的内存数据库,所有数据都存储在内存中,而内存资源是有限的——这就引出了两个核心问题:过期数据如何删除?内存满了之后新数据如何存储?这两个问题分别对应 re

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数据删除与淘汰策略内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com