导读:本期聚焦于广州程序员创作的《Redis内存淘汰策略怎么选?原理、应用场景与常见问题一次讲清》,敬请观看详情。当Redis的maxmemory达到上限后,继续写入会触发内存淘汰,选错策略可能让热点数据被清空或者所有写请求直接报错。本文围绕noeviction、allkeys-lru、allkeys-lfu、volatile-ttl等八种策略,说明它们比较候选键、采样估算空闲时间、访问频率衰减的核心原理,并对比allkeys和volatile两条范围线的差异。在应用场景部分,给出纯缓存、会话存储、排行榜、持久化队列等不同业务的推荐策略;随后梳理只配置maxmemory但未设置淘汰策略、使用volatile系列却没有为键设置TTL、主从复制与AOF重写影响内存判断等常见坑。通过redis-cli动态修改配置和观察evicted_keys指标,可以快速验证策略是否按预期生效,避免线上出现OOM或只读异常。

Redis的内存淘汰策略由maxmemory参数触发,它决定实例在内存占用达到上限后如何处理新的写命令。只设置maxmemory而不配置maxmemory-policy,会沿用默认的noeviction策略,表现为写入失败、缓存突然失效。要真正控制内存,需要从淘汰范围、筛选算法两个维度理解八种策略,并结合业务访问模型做选择。

Redis内存淘汰策略怎么选?原理、应用场景与常见问题一次讲清

当Redis执行SET、LPUSH、SADD等可能增加内存占用的命令时,会先检查当前已用内存是否超过maxmemory。如果没有超过,直接执行;如果已经达到上限,就根据maxmemory-policy选择若干键删除,直到能够满足本次写入需求。默认的noeviction策略不会删除数据,只会返回错误,这也是很多线上写入异常的原因之一。

一、八种内存淘汰策略的原理拆解

Redis目前提供了八种内存淘汰策略,名称中的allkeys表示从所有键中选取候选键,volatile表示只从设置了过期时间即TTL的键中选取。两者混用时要特别注意:如果实例中大量键没有设置TTL,volatile系列策略即使触发,也可能找不到足够多的键来释放内存,最终仍然返回OOM。

具体策略可以分为四类。LRU策略选择最近最少使用的键,Redis并不是维护一条精确的双向链表,而是利用对象头中的lru字段记录最后一次访问时间,每次淘汰时随机采样maxmemory-samples个键,删除其中空闲时间最长的那个。这种方式牺牲了一定精度,但避免了维护全局链表的额外开销。LFU策略从Redis 4.0开始引入,在lru字段上复用了访问频率计数,计数会随着时间衰减,目的是优先删除访问频率最低的键。random策略随机删除,ttl策略则直接比较剩余存活时间。

策略名称淘汰范围筛选依据适用方向
noeviction无不淘汰禁止丢失数据
allkeys-lru所有键最近最少使用普通缓存
volatile-lru设置了TTL的键最近最少使用缓存和永久数据混合
allkeys-lfu所有键访问频率最低热点明显的缓存
volatile-lfu设置了TTL的键访问频率最低热点明显且保留永久键
allkeys-random所有键随机选择键价值相近
volatile-random设置了TTL的键随机选择过期键价值较低
volatile-ttl设置了TTL的键剩余存活时间最短希望删除即将过期键

默认的近似LRU采样数量由maxmemory-samples参数控制,默认值为5。采样数量越大,淘汰结果越接近真实LRU,但每次淘汰时消耗的CPU也会增加。LFU则依赖另外两个参数:lfu-log-factor控制访问频率计数的增长速度,lfu-decay-time控制频率每分钟的衰减幅度。理解这些底层机制,才能解释为什么有些策略在特定负载下表现不如预期。

二、从场景出发选择内存淘汰策略

如果Redis只作为缓存使用,并且业务数据可以从数据库重新加载,一般优先选择allkeys-lru或allkeys-lfu。两者的核心区别在于:LRU关注最近一次访问距离现在多久,LFU关注一段时间内被访问了多少次。对于商品详情、新闻内容这类读取相对均匀的场景,allkeys-lru足够稳定;对于榜单、热门内容这类访问频率差异明显的场景,allkeys-lfu更容易保留真正的高频热点。

如果Redis中同时保存了需要持久保留的键和可以淘汰的缓存键,不要急着用allkeys系列,否则永久数据也可能被删除。这时可以使用volatile-lru或volatile-lfu,但必须保证所有缓存键都设置了合理的TTL。会话token、验证码这类本身就有过期时间的键,使用volatile-ttl可以优先删除即将到期的数据,减少对仍有较长有效期的会话的影响。

# Redis 缓存实例示例配置
maxmemory 2gb
maxmemory-policy allkeys-lfu
maxmemory-samples 10
lfu-log-factor 10
lfu-decay-time 1

上面配置适合热点访问明显的纯缓存实例。maxmemory设置为2gb,策略选择allkeys-lfu,采样数提高到10,可以让淘汰判断更接近真实访问频率。lfu-log-factor越大,访问次数增长越慢,计数器越能区分高频键;lfu-decay-time设为1表示每分钟对频率计数做一次衰减,避免历史热度永远占据优势。

如果业务写入压力不大,但对数据丢失极度敏感,可以考虑使用noeviction,并配合另一个只保存缓存的Redis实例。这样持久化数据实例绝不会因为内存压力而删除键,缓存实例即使淘汰全部数据也不会影响核心业务。这种方式会增加部署成本,但在订单、账户、配置中心等场景中很有价值。

三、常见问题与注意事项

最容易踩到的坑是只配置maxmemory,却没有修改maxmemory-policy。默认策略是noeviction,当内存达到上限后,写入命令会返回OOM错误,而读取命令仍然正常。如果监控只看接口成功率,可能误以为是数据库或网络问题。上线前应该通过CONFIG GET maxmemory-policy确认当前策略,而不是只检查maxmemory数值。

另一个高频问题是使用volatile-lru、volatile-lfu或volatile-ttl时,大量键没有设置过期时间。Redis只会从设置了TTL的键中挑选淘汰对象,如果这类键数量很少,哪怕实例中其他键占用了大量内存,也不会被删除,最终写入仍会失败。要使用volatile系列策略,就必须在写入缓存键时同步设置EXPIRE、PEXPIRE或使用SETEX命令。

主从复制架构下,内存淘汰策略还可能带来主从切换后的行为差异。主库淘汰键后会向从库同步DEL命令,从库按照复制链路执行删除,这本身不会让从库主动淘汰数据。但如果从库被提升为主库,而它自己的maxmemory-policy配置与旧主库不一致,新的写入可能触发完全不同的淘汰结果。因此建议主从实例统一配置相同的maxmemory和maxmemory-policy,避免切换后出现写失败或大面积误删。

AOF重写和持久化也可能影响内存表现。AOF重写会通过写时复制创建子进程,重写期间主库对键的修改会让父子进程共享的内存页发生复制,导致实际物理内存短暂上升。即使Redis的used_memory没有超过maxmemory,RSS依然可能超过限制。如果服务器没有预留足够内存,操作系统的OOM killer可能会触发。内存碎片同理,maxmemory只基于used_memory计算,碎片的增长不会直接触发淘汰,却会让RSS持续膨胀。

四、验证淘汰策略与调优建议

线上调整策略时,不建议直接修改配置文件后重启,可以先通过redis-cli动态修改并观察效果。CONFIG SET命令即时生效,确认无误后再执行CONFIG REWRITE将配置写回redis.conf。下面是一个临时压低内存上限并测试allkeys-lru效果的示例。

redis-cli CONFIG SET maxmemory 5mb
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG SET maxmemory-samples 10
redis-cli CONFIG REWRITE

执行写入压测后,可以通过INFO stats观察evicted_keys字段。如果该数值持续增长,说明淘汰策略正在生效;如果写入大量键后evicted_keys仍然为0,则要检查maxmemory是否设置得过低、策略是否为noeviction,或者是否所有键都没有过期时间导致volatile系列无法选择候选键。

for i in $(seq 1 10000); do
  redis-cli set key:$i value:$i > /dev/null
done
redis-cli INFO stats | grep evicted_keys

除了evicted_keys,还可以关注keyspace_hits和keyspace_misses。如果淘汰策略设置合理,缓存命中率应该保持稳定;如果命中率明显下降,可能是allkeys-random或采样数过低导致高频键被误删。对于LFU策略,若发现新写入的键很快被淘汰,可以适当降低lfu-log-factor,让初始访问频率增长更快一些;如果热点反而被低频率数据挤掉,则可以提高lfu-log-factor或减小lfu-decay-time。

最后需要明确,内存淘汰策略解决的是达到maxmemory上限后的写入问题,它不能替代合理的TTL设计。大量过期键如果不被访问,Redis不会立即释放它们占用的内存,过期删除和内存淘汰是两套独立机制。评估内存压力时,应同时查看used_memory、used_memory_rss、maxmemory以及evicted_keys,才能准确判断是否需要调整策略、提高maxmemory,或者从应用层减少缓存体量。

Redis内存淘汰策略缓存淘汰算法Redis配置优化修改时间:2026-09-21 08:06:34

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