百度面试官:Redis 内存满了怎么办?你有想过吗?

面试考察点

  1. 基础掌握度 :面试官不仅仅是想知道 Redis 有过期策略,更是想知道你是否清楚 Redis 采用的是**惰性删除 + 定期删除**的组合方案,而不是定时删除,以及为什么要这样设计。
  2. 原理理解深度:考察你是否了解过期字典的内部结构,定期删除的采样逻辑(随机抽取、循环检测),以及这些设计背后的性能与内存权衡。
  3. 知识关联能力 :能否自然过渡到 "过期策略解决不了内存问题时怎么办" → 内存淘汰策略maxmemory-policy),展示完整的知识体系。

核心答案

Redis 采用惰性删除 + 定期删除两种策略配合使用:

一句话结论 :Redis不使用定时删除 (到期立即删),因为那会消耗大量 CPU 资源。而是用 "惰性 + 定期" 的组合策略,在 CPU 和内存之间取一个平衡。如果过期策略清理不过来,内存还是满了,就会触发内存淘汰策略

深度解析

一、三种过期策略的理论对比

在讲 Redis 的方案之前,先了解一下理论上过期策略有三种:

img

上图展示了三种过期策略的理论对比:

  • 定时删除 :每个 Key 设置一个定时器,到期立即删除。内存最优,但 CPU 开销太大,Redis没有采用
  • 惰性删除 :只在访问时检查。CPU 最友好,但过期不访问的 Key 会一直占内存,Redis采用
  • 定期删除 :每隔一段时间抽查。是 CPU 和内存的折中方案,Redis采用

Redis 选择惰性 + 定期的组合策略,既不会消耗过多 CPU,又能及时清理大部分过期数据。

二、过期字典:Redis 如何记录 Key 的过期时间?

img

上图展示了 Redis 存储过期时间的内部结构:

  • Redis 在每个数据库(redisDb)中维护了两个字典:dict (主字典,存储所有 Key-Value 数据)和 expires(过期字典,存储设置了过期时间的 Key 及其过期时间戳)。
  • 过期字典的 key 指向主字典中的同一个 Key 对象(不是副本),所以不会额外占用太多内存。
  • 当检查一个 Key 是否过期时,只需在expires字典中查找对应的时间戳,与当前时间比较即可。

三、惰性删除的工作流程

img

上图展示了惰性删除的判断流程:

  • 核心思路:每次访问 Key 时,顺便检查一下是否过期。如果过期了,就删除并返回空;没过期就正常返回数据。
  • 优点:对 CPU 极度友好,只有在业务需要访问时才执行删除操作,不会浪费 CPU 资源。
  • 缺点 :如果有些 Key 过期了但一直没有被访问,它们就会一直占用内存,成为 "垃圾数据"。

四、定期删除的工作流程

定期删除是 Redis 主动清理过期数据的机制,它的执行逻辑比惰性删除复杂得多。

img

上图展示了定期删除的完整流程,核心逻辑:

  • 随机抽取:每 100ms 从过期字典中随机抽取 20 个 Key,检查是否过期。
  • 自适应循环:如果这 20 个 Key 中过期的比例超过 25%,说明当前过期 Key 很多,就再随机抽 20 个继续清理,直到过期比例降到 25% 以下,或者执行时间超过上限(默认 25ms)。
  • 为什么限制 25ms:定期删除是在 Redis 主线程中执行的,如果清理时间过长会阻塞正常请求,所以必须严格限制单次执行时长。

定期删除的局限性

  • 由于是随机抽样,总会有一些过期 Key 被遗漏,不会全扫一遍。
  • 如果过期 Key 数量非常多,而随机抽取的概率有限,仍然会有大量过期 Key 残留在内存中。

五、过期策略 + 内存淘汰策略 = 完整方案

"惰性 + 定期" 只能清理过期了的 Key 。如果有些 Key 没有设置过期时间,或者过期策略清理速度跟不上新 Key 的写入速度,内存还是会满。这时就需要内存淘汰策略出场了。

arduino 复制代码
# redis.conf 配置最大内存和淘汰策略
maxmemory 4gb
maxmemory-policy allkeys-lru

Redis 8 种内存淘汰策略

生产环境推荐allkeys-lru(通用缓存)或allkeys-lfu(热点明显的缓存)。

面试高频追问

  1. 追问一:为什么 Redis 不用定时删除?

    定时删除需要为每个设置了过期时间的 Key 维护一个定时器,如果同时有几十万个 Key 设置了过期时间,就会有几十万个定时器同时运行,严重消耗 CPU 资源,影响 Redis 处理正常请求的性能。Redis 作为高性能缓存,把 CPU 留给业务处理更重要。

  2. 追问二:LRU 和 LFU 淘汰策略的区别?

  • LRU(Least Recently Used) :淘汰最久没被访问的 Key,基于 "最近访问的数据大概率还会被访问" 的假设。Redis 的 LRU 是近似算法,随机采样 N 个 Key(默认 5 个),淘汰其中最久未访问的。

  • LFU(Least Frequently Used) :淘汰访问频率最低的 Key,基于 "访问频率高的数据更有价值" 的假设。Redis 4.0 引入,更适合热点数据明显的场景(比如 20% 的数据占 80% 的访问量)。

  • 追问三:如何查看 Redis 当前内存使用情况?

    bash 复制代码
    # 查看内存使用详情
    INFO memory
    
    # 关键指标:
    # used_memory:已用内存
    # maxmemory:最大内存限制
    # maxmemory_policy:当前淘汰策略

常见面试变体

  • 变体一:"Redis 的 Key 过期了是怎么被删除的?"
  • 变体二:"Redis 过期策略和内存淘汰策略的区别?"
  • 变体三:"Redis 内存满了怎么办?"
  • 变体四:"Redis 的 LRU 算法了解吗?是精确的还是近似的?"

记忆口诀

过期策略:惰性删除(访问才删)+ 定期删除(随机抽查,过期超 25% 继续抽)。

为什么不单独用一种:惰性删不干净(残留垃圾),定期删不精确(随机抽样),两者互补。

内存满了 :过期策略搞不定 → 内存淘汰策略接手 →allkeys-lru最常用。

总结

Redis 过期策略采用惰性删除 + 定期删除 的组合方案。惰性删除在访问时才检查并删除过期 Key,对 CPU 友好;定期删除每 100ms 随机抽样一批 Key 清理过期的,防止大量过期数据残留。两者互补,在 CPU 和内存之间取得平衡。如果过期策略仍无法释放足够内存,就会触发内存淘汰策略 (推荐allkeys-lruallkeys-lfu)。

相关推荐
喵个咪2 小时前
Headless 架构优势:内容与展示解耦,一套 API 打通全端生态
前端·后端·cms
开心就好20252 小时前
HTTPS超文本传输安全协议全面解析与工作原理
后端·ios
小江的记录本2 小时前
【JEECG Boot】 JEECG Boot——数据字典管理 系统性知识体系全解析
java·前端·spring boot·后端·spring·spring cloud·mybatis
神奇小汤圆2 小时前
Spring Batch实战
后端
喵个咪2 小时前
传统 CMS 太笨重?试试 Headless 架构的 GoWind,轻量又强大
前端·后端·cms
程序员木圭2 小时前
07-数组入门必看!Java数组的内存分析02
java·后端
喵个咪2 小时前
Go 语言 CMS 横评:风行 GoWind 对比传统 PHP/Java CMS 核心优势
前端·后端·cms
面向Google编程2 小时前
从零学习Kafka:位移与高水位
大数据·后端·kafka
Honmaple2 小时前
驾驭AI的黄金缰绳:Harness Engineering引领2026工程范式变革
后端