Redis 作为内存数据库,内存管理是运维和面试中的高频考点。其中 maxmemory 和 maxmemory-policy 两个配置项直接决定了 Redis 在内存不足时的行为,理解它们的工作原理,是避免线上故障的关键。
为什么需要设置 maxmemory
Redis 默认对内存使用没有硬性限制(64 位系统下默认为 0,表示不限制),它会尽可能使用服务器上的空闲内存。这在生产环境中非常危险:一旦内存被耗尽,可能触发操作系统的 OOM Killer,导致 Redis 进程被强制杀死,或者引发 swap 交换,使性能急剧下降。
通过设置 maxmemory,我们可以为 Redis 指定一个内存使用上限。当已用内存达到该阈值时,Redis 会根据 maxmemory-policy 采取相应措施,比如淘汰部分键或拒绝写入请求。
配置方式有两种:
# redis.conf 中
maxmemory 4gb
maxmemory-policy allkeys-lru
# 运行时动态修改
redis-cli config set maxmemory 4gb
redis-cli config set maxmemory-policy allkeys-lru
需要注意,maxmemory 统计的是 Redis 实际使用的内存总量,包括数据、缓冲区、复制 backlog 等。如果只设置了 maxmemory 而没有设置合理的淘汰策略,当内存达到上限且策略为 noeviction 时,所有写命令都会返回错误。
maxmemory 的计量口径
很多面试题会追问:maxmemory 到底算的是什么内存?它对应 used_memory 这个指标,而不是 used_memory_rss。used_memory 是 Redis 自身统计的分配器分配出去的内存,不含内存碎片和部分运行时开销。因此实际进程占用的物理内存(RSS)通常会略大于 maxmemory。在容器化环境中,如果给容器设置了内存 limit,建议 maxmemory 留出 20%~30% 的余量,避免因碎片或缓冲区导致容器被 OOM Kill。
八种 maxmemory-policy 详解
maxmemory-policy 决定了内存达到上限后的处理方式,共有八种取值,可分为“淘汰类”和“拒绝写入类”。
淘汰类策略
- noeviction:不淘汰任何键,当内存不足时,写命令直接返回错误,读命令仍可执行。这是默认策略,适合数据不允许丢失的场景,但需要应用层处理写入失败。
- allkeys-lru:从所有键中,淘汰最近最少使用的键(LRU)。这是最常用的策略,适合缓存场景。
- allkeys-lfu:从所有键中,淘汰使用频率最低的键(LFU,Redis 4.0 引入)。相比 LRU,它更能抵抗偶发的一次性访问,适合热点数据明显的场景。
- allkeys-random:从所有键中随机淘汰。适合访问分布均匀、无热点的情况。
- volatile-lru:只从设置了过期时间的键中,淘汰最近最少使用的。
- volatile-lfu:只从设置了过期时间的键中,淘汰使用频率最低的。
- volatile-random:只从设置了过期时间的键中随机淘汰。
- volatile-ttl:只从设置了过期时间的键中,优先淘汰剩余生存时间最短的键。
“volatile-” 前缀的策略有一个重要前提:如果没有任何键设置了过期时间,那么这些策略的行为等同于 noeviction,写命令会报错。这一点是面试中的常见陷阱。
LRU 与 LFU 的实现差异
Redis 的 LRU 并非精确实现,而是近似 LRU。它没有维护完整的链表,而是在每个对象的 redisObject 中记录一个 24 位的 lru 字段(时间戳)。淘汰时,Redis 随机采样 maxmemory-samples 个键(默认 5),从中选出最久未使用的那个淘汰。采样数越大,越接近真实 LRU,但 CPU 开销也越高。
LFU 则把 24 位字段拆成两部分:高 16 位记录访问时间(分钟级),低 8 位记录访问频率计数器(0~255)。计数器采用概率递增,访问越频繁增长越慢,并会随时间衰减。这样既能反映热度,又能让冷数据逐渐被淘汰。
可以这样理解:LRU 关注“多久没被访问”,LFU 关注“被访问了多少次”。对于突发的全表扫描,LRU 可能把热点数据挤出去,而 LFU 因为热点数据计数器高,更能守住阵地。
如何选择合适的策略
- 纯缓存场景,数据可重建:优先
allkeys-lru;若热点集中且访问频率差异大,选allkeys-lfu。 - 缓存 + 持久数据混合:用
volatile-lru或volatile-lfu,只淘汰有 TTL 的键,保护持久数据。 - 数据绝对不能丢:用
noeviction,并在应用层做好写入失败的处理,同时监控内存。 - 访问模式随机、无热点:
allkeys-random即可。
实践中的注意事项
第一,淘汰策略只在内存达到 maxmemory 时触发,平时不会主动清理。第二,主从架构下,从库的淘汰由主库同步的 DEL 命令驱动,从库自身不会独立淘汰(除非它自己的内存也超限)。第三,使用 volatile-* 策略时,要确保有足够的键设置了过期时间,否则会退化为 noeviction。第四,可以通过 INFO stats 中的 evicted_keys 观察淘汰数量,如果该值持续增长,说明内存吃紧,需要考虑扩容或优化数据结构。
建议的监控组合是:used_memory、maxmemory、evicted_keys、keyspace_hits/misses。当命中率下降且 evicted_keys 上升时,往往意味着需要调整策略或增加内存。
面试高频问题小结
maxmemory为 0 代表什么?——不限制内存。noeviction下写命令会怎样?——返回 OOM 错误。volatile-lru在没有 TTL 键时表现如何?——等同noeviction。- LRU 是精确的吗?——不是,是采样近似。
- LRU 和 LFU 的核心区别?——时间维度 vs 频率维度。
maxmemory-samples的作用?——控制采样精度与 CPU 开销的平衡。
掌握这两个配置项,不仅能应对面试,更能在实际运维中避免因内存失控导致的服务不可用。合理设置上限、选对淘汰策略、持续监控关键指标,才是 Redis 内存管理的完整闭环。
未经允许不得转载:任鹏个人博客 » Redis 的 maxmemory 和 maxmemory-policy 配置详解

