如果发现 Redis 内存溢出了?你会怎么做?请给出排查思路和解决方案

Sherwin.Wei Lv7

如果发现 Redis 内存溢出了?你会怎么做?请给出排查思路和解决方案

回答重点

遇到线上问题,第一时间是止损,如果发现 Redis 内存溢出,则应该立即扩容,增加 Redis 实例的内存,保证线上业务正常运行。

image.png

然后再排查内存溢出的可能原因:

  • 数据过多: Redis 中存储的数据量过大,超过了可用内存。
  • 数据过期策略失效: 大量的 key 没有设置过期时间,导致内存不断增长。
  • 大对象或大数据结构: 某些 key 关联的数据结构(如 hash、list、set)过于庞大,占用了大量内存。
  • 持久化机制影响:RDB 采用写时复制,极端情况下会占用正常两倍的内存

常见优化方案:

  • 调整内存淘汰策略: 根据业务需求选择合适的淘汰策略,如 allkeys-lru 或 volatile-lru,以便在内存接近上限时能够自动删除较少使用的 key。
  • 设置数据过期时间: 对重要的数据设置合理的过期时间,避免无用数据长期占用内存。
  • 优化数据结构: 检查大对象或大数据结构的使用情况,优化存储方案,如将大型 hash 拆分成多个小 hash。
  • 垂直扩展: 升级单台 Redis 配置。
  • 水平扩展: 将数据分片到多个 Redis 实例,使用集群或分布式缓存来减轻单实例的内存压力。
  • 数据持久化调整: 优化持久化策略,减少额外的内存消耗,例如在低峰期触发 RDB 备份数据。

扩展知识

监控告警

针对线上的一些中间件,不论是 Redis、MySQL、MQ 等,都需要针对实例对应机器的基础信息(CPU/内存/IO)和业务信息(key数量、表大小、消息堆积量等)进行监控。超过一定阈值后告警,使得我们可以提前发现问题、解决问题,避免事故的产生。

例如云厂商(本地则需要自己搭建)就配套提供了很多告警接入(钉钉、企微、邮件等等),在对应中间件配置内即可:

image.png

如果提前监控 Redis 的内存情况,例如占用 80% 就告警通知,那么就可以避免 Redis 内存满报错的问题。

问题排查思路

观测一段时间 Redis 的内存使用量,如果发现从某一天开始,内存使用量开始明显增加,再结合那段时间的发版情况,复查那个版本提交的代码中涉及 Redis 操作,即可快速定位到问题。

image.png

如果是代码 bug 则修复代码。

如果是正常业务功能增加导致需要缓存的数据变多,则思考是否可以精简存储 value,并考虑是否可以设置过期时间,或过期时间是否可以再短一些。

最终优化后,如果确定目前的应用就是占用这么多内存,则只能扩容。

Redis 持久化

Redis 持久化

Redis 淘汰机制

Redis 淘汰机制

Redis 过期策略

Redis 过期策略

Comments