Redis内存满了:查占用与设置淘汰策略

Redis 提示内存不足,先看它是否还在运行:OOM command not allowed when used memory > 'maxmemory'通常是 Redis 拒绝了会增加内存的命令;进程消失、连接被拒绝或容器反复重启,则需要同时查系统或容器的内存限制。两种情况的处理步骤不同。

本文针对 Linux 上自行管理的 Redis 7 及以后单机实例。集群、主从切换或托管服务还要核对各节点和平台配置入口。基础登录方式见Redis 安装与连接教程。

先保留运行数据,再决定改哪里

在 Redis 所在服务器连接本机实例。这里使用默认账号;非默认 ACL 账号增加 --user 实际账号名,端口也按实际配置替换。通过交互提示输入密码,避免写进命令历史:

redis-cli -h 127.0.0.1 -p 6379 --askpass

以下命令在 Redis 提示符内执行。先记录当前值,便于比较和回退;账号没有管理权限时,由有权限的管理员处理。

INFO server
INFO memory
INFO stats
CONFIG GET maxmemory
CONFIG GET maxmemory-policy
重点字段 怎样理解
used_memory Redis 分配的内存,用来观察数据与内部开销的变化。
used_memory_rss 操作系统看到的驻留内存,可能明显高于前一项,不能把两者当成同一个数字。
maxmemory Redis 自身的内存控制值。64 位实例设为 0,表示未设置这项上限。
mem_not_counted_for_evict 不计入淘汰判断的部分内存,例如某些复制和持久化缓冲,主机仍要为它们留空间。
evicted_keys 因内存压力被淘汰的键累计数,应比较一段时间内的增量。

maxmemory不是 Redis 进程的绝对峰值。系统、其他应用、碎片和持久化期间的额外内存都需要预算;容器或系统服务还可能有比物理内存更低的限制。

从业务键找原因,先别清空数据库

挑选应用已确认的可疑键,查看类型、过期时间和内存占用。应用没有使用默认 0 号库时,先用 SELECT 实际库编号进入对应逻辑库。下面的键名是示例:

TYPE cache:example
TTL cache:example
MEMORY USAGE cache:example SAMPLES 5

TTL返回 -1 表示没有过期时间,-2 表示键不存在;MEMORY USAGE返回字节数,嵌套类型会按采样估算。一次只查少量已知键,避免为了找大键在繁忙实例上执行全库 KEYS *或对巨大集合逐项扫描。

如果同类缓存持续增长,检查应用是否漏设 TTL、缓存键是否包含不断变化的无用参数、列表或集合是否没有长度边界。清理只针对业务负责人确认可以删除的数据;不要把 FLUSHALL当作修复内存问题的常规步骤。

淘汰策略先按数据用途选

数据用途 处理方向
所有键都能重新生成的独立缓存 可评估 allkeys-lru或allkeys-lfu,并检查缓存命中率和后端回源压力。
只允许淘汰设置了过期时间的缓存键 可评估 volatile-lru等策略;没有符合条件的键时,仍可能报 OOM。
队列、会话或唯一业务数据不能随意丢失 保留 noeviction,处理容量、异常增长或数据拆分;应用需要正确处理写入失败。

不同用途共用一个 Redis 实例时,allkeys-*会覆盖所有键,不会自动识别哪些是订单、队列或重要会话;分到不同逻辑库也没有隔离实例内存上限。先拆分用途或确认业务约束,再决定策略。noeviction只是不按容量自动淘汰,持久化与备份仍要另外配置。

下面仅演示一个已经确认所有键可丢弃、并已核定 512 MB 容量预算的缓存实例。写入命令前记录原参数;降低上限或启用淘汰后,已有键可能立即被删除,改回参数也不能找回这些键。

CONFIG SET maxmemory 512mb maxmemory-policy allkeys-lru
CONFIG GET maxmemory
CONFIG GET maxmemory-policy
INFO memory
INFO stats

命令返回 OK 后,用实际应用做一次读写,再观察 OOM 是否停止、淘汰量是否异常、数据库回源压力是否升高。不能为了消除报错,直接把上限设成整台服务器的内存。

运行时改成功,还要保存到真正的配置来源

CONFIG SET只改变运行中的配置。先看 INFO server里的 config_file,核对启动方式并备份实际配置文件。自行管理且配置文件可写的实例,可以在确认其他运行时改动也应保留后执行:

CONFIG REWRITE

这个命令会写回当前配置与原文件的差异,不只保存刚才两个参数。没有加载配置文件、目录不可写或文件只读时会失败;容器挂载配置、配置管理系统或托管服务,应修改对应的部署来源,不要通过放宽整个目录权限来强行写入。

检查文件中的最终值;下一次计划重启后,再用 CONFIG GET核对实际加载值。若要回退,恢复此前记录的参数和配置来源,同时确认业务数据是否已经因淘汰发生变化。

如果进程被系统杀掉,回到主机查证据

退出 Redis 客户端,在 Linux 终端检查对应时段。下面的服务名 redis-server要与本机实际名称一致:

free -h
sudo journalctl -k --since "30 minutes ago" --no-pager
sudo journalctl -u redis-server --since "30 minutes ago" --no-pager

保留内核日志中是否出现 OOM、被终止进程名称等证据;Docker 部署还要核对容器的内存限额和 OOMKilled状态。只有连接错误或退出码 137,不能单独证明一定是内存不足。先对齐 Redis 上限与主机、容器预算,再决定扩容或调整负载,不要只反复重启。