不能。Redis的maxmemory-samples仅在随机采样中选空闲时间最长的key,其lru字段非实时更新,本质是启发式估算而非近似LRU;增大采样数虽提升淘汰准确性但CPU开销线性增长,且Redis原生不支持严格LRU。

Redis 的 maxmemory-samples 真的能逼近 LRU 吗?
不能。它只是在采样范围内找“看起来最久没用”的 key,不是真 LRU,也不是近似 LRU(如 LRU-K),更不是 LFU。Redis 默认的 allkeys-lru 或 volatile-lru 策略底层用的是近似 LRU:每次淘汰时随机采样 maxmemory-samples 个 key,从中挑出空闲时间最长的那个——这个“空闲时间”是基于每个 key 记录的最后一次访问时间戳(lru 字段)算出来的,但该字段只在访问、写入、过期检查等少数时机更新,并非实时。
为什么增大 maxmemory-samples 会让淘汰更“准”,但代价明显?
增大采样数,相当于在更大池子里挑“最老”的 key,统计上更可能命中真正长期未访问的 key,从而降低误删热 key 的概率。但每轮淘汰都要遍历这么多 key、读取它们的 lru 值、做比较,CPU 开销线性上升。尤其在高并发写+内存紧绷场景下,可能触发频繁淘汰,导致 eviction 耗时飙升,甚至拖慢主线程响应。
-
maxmemory-samples默认是5,对大多数业务够用;设为10~20是较稳妥的折中 - 设到
100以上,在大实例(比如 10GB+ 内存、百万级 key)上单次淘汰可能耗时几毫秒,且收益快速衰减 - Redis 7.0+ 引入了
allkeys-lru-v2(实验性),用更紧凑的链表结构优化采样逻辑,但仍未改变“采样+估算”本质
想严格 LRU?Redis 原生不支持,但有替代路径
Redis 没有维护全局访问链表(会严重拖慢写性能),所以不可能实现标准 LRU。如果业务强依赖精确访问时序淘汰(比如缓存审计、合规场景),得绕开 Redis 自身淘汰机制:
- 用
allkeys-noeviction关掉自动淘汰,自己用OBJECT IDLETIME+ 定时任务扫描淘汰——但OBJECT IDLETIME本身精度低(秒级)、不准,且扫描成本极高 - 把 key 访问记录写到外部有序集合(如另一个 Redis 实例或 TimescaleDB),用时间戳排序淘汰——增加架构复杂度和延迟
- 改用支持真正 LRU 的嵌入式库(如 C++ 的
lru_cache、Go 的container/list+map组合),但失去 Redis 的分布式、持久化、网络协议等能力
配置时最容易被忽略的三个细节
很多人调了 maxmemory-samples 就以为“更像 LRU 了”,却踩在这些坑里:
- 没确认当前
maxmemory-policy是否为*-lru类型——设成allkeys-random时,maxmemory-samples完全无效 - 用
INFO memory查evicted_keys和expired_keys时,误把两者当淘汰依据;实际淘汰行为受maxmemory和当前内存使用率共同触发,不是“一满就删” - 在集群模式下,
maxmemory-samples是节点级配置,各分片独立采样——无法跨 slot 协同,热点 key 分布不均时效果更差
真要压榨 LRU 效果,与其盲目拉高采样数,不如先用 MEMORY USAGE 和 SLOWLOG 定位是不是大 key 或突发写入导致抖动,那才是更常被忽略的根因。


















