真实面经题目 · 原创解析

Redis 内存满了会发生什么?

Redis 内存满了之后的行为取决于 maxmemory 和 maxmemory-policy:可能触发淘汰并继续写入,也可能拒绝会增加内存的写命令。回答时要说明触发时机、策略分类、近似算法以及对业务的影响。

出现于:字节跳动 · 后端开发

60 秒回答模板

Redis 内存满了不是固定直接崩溃,而是看是否配置 maxmemory 以及淘汰策略。如果没有合理限制,进程可能继续向操作系统申请内存,最终受到系统内存、OOM 或容器限制影响。如果配置了 maxmemory,写命令执行前后 Redis 会检查内存使用,超过限制就按 maxmemory-policy 淘汰 key。策略包括 noeviction、allkeys-lru、volatile-lru、allkeys-lfu、volatile-lfu、allkeys-random、volatile-random、volatile-ttl 等。noeviction 会拒绝会增加内存的写操作,读操作通常还能执行;其他策略会尝试释放空间后继续写入。如果没有可淘汰 key,也可能返回 OOM 错误。

考点 内存满的分叉
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

maxmemory 的作用

maxmemory 是 Redis 自身的内存上限控制,不等同于机器或容器的真实物理内存。配置后,Redis 会在可能增加内存的命令路径上检查是否超过限制,超过就进入淘汰流程或拒绝写入。若不配置上限,Redis 可能持续申请内存,最终风险转移给操作系统或容器运行时,出现交换、延迟抖动甚至进程被杀。

02

noeviction 的表现

当策略是 noeviction 时,Redis 不主动驱逐 key。内存超过限制后,读命令、删除命令以及部分不会增加内存的操作通常仍可执行,但会增加内存的写命令会返回 OOM 类错误。这个策略适合不允许缓存自动丢数据的场景,但业务必须能处理写失败,否则会出现请求错误或状态不一致。

03

淘汰策略的候选范围

淘汰策略的关键差异之一是候选 key 范围。allkeys 系列可以从全部 key 中淘汰,更符合纯缓存用途;volatile 系列只从设置了过期时间的 key 中淘汰,适合把带 TTL 的数据视为可牺牲对象。如果使用 volatile 策略但很多 key 没有 TTL,内存满时可能找不到足够候选 key,最终仍然写失败。

04

LRU 与 LFU 是近似算法

Redis 为了控制性能成本,并不会维护严格的全局 LRU 链表或精确访问频率排名,而是基于对象上的访问时间、频率计数和随机采样做近似选择。采样数量越大,淘汰质量越接近理想结果,但 CPU 成本也会上升。面试中说“Redis 用近似 LRU/LFU”比直接说“严格淘汰最久未使用 key”更准确。

05

业务层面的后果

内存满会带来三类业务影响:写入失败、热点缓存被驱逐、延迟升高。写入失败需要调用方识别并降级;缓存被驱逐会增加回源压力,可能形成数据库抖动;淘汰过程本身也会消耗 CPU,尤其在大 value、频繁写入、碎片率高或候选不足时更明显。合理设置 TTL、容量、淘汰策略和监控指标是必要配套。

易错点

  • 认为 Redis 内存满后一定崩溃,忽略 maxmemory-policy 的不同表现。
  • 认为 noeviction 是不影响业务的安全策略,实际上它会让写命令失败。
  • 使用 volatile 策略却不给 key 设置 TTL,导致满内存时没有足够候选对象。
  • 把 Redis 的 LRU/LFU 说成绝对精确排序,忽略随机采样和近似实现。

面试官追问

Redis 内存满了一定会删除 key 吗?

不一定。只有配置了会淘汰的 maxmemory-policy 时才会尝试删除 key。若策略是 noeviction,或者没有合适候选 key,Redis 会拒绝部分写命令。

allkeys-lru 和 volatile-lru 怎么选?

如果 Redis 主要作为缓存,通常 allkeys-lru 更直接,因为所有 key 都可被淘汰。如果同一个实例里有不能丢的数据,应避免混用或使用 volatile-lru 并确保可淘汰数据都设置 TTL。

为什么淘汰后还是可能 OOM?

可能是没有可淘汰 key、单次写入对象太大、内存碎片明显、淘汰速度赶不上写入速度,或者策略候选范围过窄。淘汰不是无限保证写入成功,只是尽力释放空间。

内存满和过期删除有什么关系?

过期删除会释放已经到期的 key,有助于降低内存;但内存满时触发的是淘汰流程,可以淘汰未过期 key。两者目标不同,一个按时间失效,一个按容量压力驱逐。