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 上限与主机、容器预算,再决定扩容或调整负载,不要只反复重启。