Redis 内存满了怎么办?我说“加内存”,面试官让我出去……

51 阅读5分钟

最近有个兄弟去面试,回来跟我吐槽,说面试官太刁钻了。

面试官问他:“假设线上的 Redis 内存报警了,使用率飙到了 95%,你第一反应怎么处理?”

这兄弟想都没想,直接说:“找运维申请扩容,加内存呗。”

面试官盯着他看了两秒,问:“那如果扩容后又满了呢?一直加下去?公司预算是你家出的?”

这兄弟当场就卡壳了。

其实,这道题在面试里出现的频率非常高。它考察的不是你还会不会扩容,而是考察你有没有**“治理思维”“成本意识”**。

今天我们就来聊聊,当 Redis 内存告急时,除了“加钱”,我们还能做什么。

第一步:别急着扩容,先看策略

很多时候,内存满是因为配置没设好。

Redis 有一个关键参数叫 maxmemory,决定了它能用多少内存。当数据量达到这个限制时,Redis 会怎么做?这就取决于另一个参数:maxmemory-policy(内存淘汰策略)

很多公司默认配置是 noeviction。这个策略的意思是:内存满了就不让写了,任何写入操作(SET、LPUSH 等)都会直接报错(OOM command not allowed),但读操作还能正常进行。这会导致线上业务直接不可用。

所以,你首先要检查的是:我们是不是存了太多根本不用的数据?

如果你的业务允许数据丢失(比如只是做缓存),应该把策略调整为 allkeys-lru 或者 volatile-lru

  • allkeys-lru:不管有没有设置过期时间,优先删除最近最少使用的 key。
  • volatile-lru:只删除设置了过期时间的 key 中,最近最少使用的那部分。

改成 LRU 策略后,Redis 会自动把那些很久没人访问的冷数据清理掉,内存水位自然就降下来了。

第二步:谁占了内存?揪出 Big Key

如果淘汰策略已经开了,内存还是降不下来,或者业务要求数据不能随便丢,那就要找原因了:到底是什么东西占用了这么多内存?

通常有两种情况:

  1. Key 的数量太多:几千万、上亿个 Key。
  2. 存在超大 Key(Big Key):比如一个 Hash 结构里存了 100 万个字段,或者一个 List 里塞了 500 万条数据。

怎么找?千万别在生产环境直接敲 keys *,这会导致 Redis 阻塞,整个服务卡死。

你应该用 Redis 自带的工具:

redis-cli --bigkeys

或者在 Redis 4.0 以后,使用 memory usage 命令去抽查。

找到这些大 Key 后,通常会发现:

  • 有的 Key 是日志数据,写进去就没读过。
  • 有的 Key 是某些临时列表,越积越多,忘了删。

第三步:怎么删?千万别用 DEL

找到大 Key 了,比如一个叫 user:rank:list 的列表,占用 2GB 内存。

很多人的直觉反应是:DEL user:rank:list

千万别这么干!

Redis 是单线程处理命令的。删除一个 2GB 的 Key,意味着 Redis 要在主线程里一次性释放这 2GB 的内存空间。这个过程非常耗时,可能需要几百毫秒甚至几秒。

在这几秒钟里,Redis 无法处理任何其他请求(比如用户的登录、下单),这就叫**“阻塞”**。

正确的做法是使用 UNLINK 命令(Redis 4.0+):

UNLINK user:rank:list

UNLINK 是非阻塞的。它会把这个 Key 从键空间里摘除(逻辑删除),然后把释放内存的繁重工作丢给后台线程去慢慢做(物理删除)。这样就不会卡住主线程。

如果你的 Redis 版本很老,不支持 UNLINK,那就必须**“分批删除”**。比如是 Hash,就用 HSCAN 每次扫 1000 个字段,分多次 HDEL 删掉。

第四步:给 Key 加上过期时间

最后,要从源头解决问题。

很多开发习惯不好,写代码时只管 SET,不管 EXPIRE(过期时间)。结果就是数据只进不出,内存迟早要爆。

一定要定个规矩:所有的缓存 Key,必须设置过期时间。 哪怕设长一点(比如 30 天)也比永不过期强。这样 Redis 才能利用 volatile-lru 策略自动循环利用内存。

总结:面试怎么答?

回到开头的面试题。如果再被问到“Redis 内存满了怎么办”,你可以按这个逻辑回答,绝对稳:

  1. 先不谈扩容:先排查配置和数据,扩容是最后的手段。
  2. 检查淘汰策略:确认 maxmemory-policy 是否合适,是不是因为默认的 noeviction 导致无法写入,建议改为 LRU 策略自动清理冷数据。
  3. 分析大 Key:使用 --bigkeys 工具分析内存分布,找出占用巨大的异常 Key。
  4. 安全删除:发现大 Key 后,使用 UNLINK 异步删除,避免阻塞主线程。
  5. 兜底方案:如果以上做完,内存确实不够用(全是热数据),那再带着分析报告去找运维扩容。

这样回答,既展示了技术深度,又体现了你对线上稳定性的敬畏。

END

⚡️ 别把时间浪费在低效复习上

很多人复习抓不住重点。作为过来人,我分析了100+份大厂面试记录,将 Go/Java/AI 的核心考察点、高频题、易错点 浓缩进了一份 PDF。

不搞虚的,全是干货。

加我微信:wangzhongyang1993,备注 【面经】 免费发你,立即纠正你的复习方向,把时间用在刀刃上。

wangzhongyang.com 也欢迎大家直接访问我的官网,里面有Go / Java / AI 的资料,免费学习