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控制默认 hz10hz 的值表示「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 中「最近最少使用」的 keyLRULeast Recently Used通用场景大多数业务如缓存、会话存储✅ 非常常用volatile-lru只淘汰「设置了过期时间」的 key 中最近最少使用的 key需要保留未过期 key如核心配置只淘汰临时缓存✅ 常用allkeys-random随机淘汰所有 key 中的任意一个对 key 访问频率无要求追求简单高效❌ 不常用volatile-random只随机淘汰「设置了过期时间」的 key同上且需要保留未过期 key❌ 不常用volatile-ttl只淘汰「设置了过期时间」的 key 中剩余过期时间最短ttl 最小的 key希望尽快淘汰即将过期的临时缓存⚠️ 场景化常用volatile-lfu只淘汰「设置了过期时间」的 key 中最不经常使用的 keyLFULeast Frequently Usedkey 访问频率差异大优先保留高频访问 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 淘汰的这里给出简化版原理不用深入源码理解即可对于 LRURedis 给每个 key 维护一个「最后访问时间戳」淘汰时遍历候选 key根据淘汰范围筛选出时间戳最小最近最少访问的 key 进行删除。对于 LFURedis 给每个 key 维护一个「访问计数器」每次访问 key 时计数器加 1每隔一段时间计数器会衰减避免旧的高频 key 一直占用淘汰时筛选出计数器最小最不经常使用的 key 进行删除。注意Redis 的 LRU/LFU 并非「严格意义上的全量排序」全量排序会消耗大量 CPU而是通过「采样排序」实现——每次淘汰时随机抽取一定数量的 key默认 5 个可通过maxmemory-samples配置在采样的 key 中选择最该淘汰的兼顾性能和准确性。四、核心配置实战生产环境必看了解了删除和淘汰策略后最关键的是「生产环境如何配置」避免内存溢出或数据异常。以下是核心配置项和推荐配置1. 核心配置项说明配置项作用推荐值maxmemory设置 Redis 最大可用内存必须配置否则内存会无限增长导致服务器内存溢出根据服务器内存配置建议设置为服务器内存的 50%-70%如 8G 内存设置为 4Gmaxmemory-policy设置数据淘汰策略通用场景allkeys-lfu有核心未过期 keyvolatile-lfuhz定期删除的频率每秒执行次数默认 10内存压力大时可调整为 20maxmemory-samplesLRU/LFU 淘汰时的采样数量默认 5采样数量越多淘汰越精准但 CPU 占用越高建议保持默认2. 推荐配置示例redis.conf# 设置最大内存为 4G maxmemory 4gb # 淘汰策略所有 key 中最不经常使用的 maxmemory-policy allkeys-lfu # 定期删除频率每秒 10 次 hz 10 # LFU 采样数量5 个 maxmemory-samples 53. 动态调整配置无需重启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. 问题4LRU 淘汰策略不精准原因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 清理的监控方法不同业务场景缓存、会话、配置存储的具体策略配置。