Redis 内存占用越来越高怎么办?淘汰策略、碎片率与持久化内存排查指南

Redis 内存占用持续升高,可能是数据增长、TTL 缺失、碎片率偏高、持久化 fork 或复制缓冲造成。本文按 INFO memory、keyspace、大 key、淘汰策略、持久化和复制的顺序,给出完整排查路径与扩容前检查项。
Redis 内存占用越来越高怎么办?淘汰策略、碎片率与持久化内存排查指南

Redis 内存占用持续升高,常见原因有三类:数据量确实在增长;键没有设置合理过期时间;淘汰策略、碎片率或持久化机制让内存没有按预期释放。本文按线上排查顺序拆解 used_memory、used_memory_rss、碎片率、key 数量、过期策略和持久化影响,帮助你判断该清理数据、调参数还是扩容。

内存升高不一定等于泄漏。Redis 的很多设计会把删除和回收延后执行,部分内存还会交给分配器持有。先用指标判断内存花在哪里,再决定是否调整,避免把业务热数据误删。

一、先分清三个内存指标

连接 Redis 后先查看整体状态:

redis-cli INFO memory

重点看这些字段:

  • used_memory:Redis 分配器分配给数据结构和内部使用的内存。
  • used_memory_rss:操作系统进程视角占用的物理内存。
  • used_memory_dataset:数据集本身占用,扣除复制积压缓冲、客户端缓冲等开销。
  • mem_fragmentation_ratioused_memory_rss / used_memory 的比值。
  • maxmemory:配置的最大可用内存,0 表示未限制。

如果 used_memory 和键数量同步增长,优先查业务写入和过期策略。如果 used_memory 稳定但 used_memory_rss 很高,可能是碎片或分配器没有归还内存。如果 maxmemory 为 0,Redis 不会主动限制数据规模,直到操作系统内存不足。

碎片率的常见判断方式:

  • 1.0 到 1.5:多数场景可以接受。
  • 明显高于 1.5:碎片偏多,要结合删除模式、页大小和 activedefrag 判断。
  • 低于 1.0:常见于 Redis 使用 swap 或操作系统内存统计口径变化,需要先查系统内存压力。

二、确认是键增长还是单键变大

键数量是最直接的入口:

redis-cli DBSIZE

redis-cli INFO keyspace

输出里的 keys 表示键数量,expires 表示带过期时间的键数量,avg_ttl 是平均 TTL 的采样值。如果键数量持续上涨而 expires 很少,说明大量数据没有生命周期,缓存可能被当成永久存储使用。

接着按类型和大小采样:

redis-cli –bigkeys

redis-cli –memkeys

--bigkeys 只能采样,适合快速发现大集合;--memkeys 会按内存排序输出键,但需要内存分析支持。采样会带来额外开销,生产环境应放在低峰期执行,避免长时间扫描。

定位到可疑键后,再看具体类型、长度和编码:

redis-cli MEMORY USAGE

redis-cli OBJECT ENCODING

redis-cli DEBUG OBJECT

DEBUG OBJECT 会返回低层信息,部分托管 Redis 会禁用 DEBUG 命令。普通运维排查优先使用 MEMORY USAGE 和业务侧键命名规范定位归属。

三、过期和淘汰策略要一起看

先看当前配置:

redis-cli CONFIG GET maxmemory

redis-cli CONFIG GET maxmemory-policy

常用淘汰策略的行为不同:

  • noeviction:写满后新写入报错,读操作可以继续。适合把 Redis 当存储使用的场景。
  • allkeys-lru:从所有键里淘汰最近最少使用的键,常见缓存场景。
  • volatile-lru:只淘汰设置了过期时间的键。如果没有键带 TTL,行为会接近写失败。
  • allkeys-lfu:按访问频率淘汰,适合热点明显的缓存。
  • volatile-ttl:优先淘汰剩余存活时间较短的键。
  • allkeys-randomvolatile-random:随机淘汰,通常较少用于核心业务。

策略选择要和数据定位一致。缓存可以按命中率选择 LRU 或 LFU;如果 Redis 保存订单、队列、Session 等仍有业务语义的数据,直接配置 allkeys 类策略可能删掉关键数据。生产修改前先记录原值,用 CONFIG SET 小范围验证,再写入配置文件和部署模板。

四、删除之后内存没有下降的原因

Redis 删除键后,内存不一定会立刻还给操作系统。进程分配器可能继续持有已释放页,used_memory_rss 因此保持较高水平。这种情况要看 used_memory 是否已经下降,如果业务侧内存指标正常,只是 RSS 偏高,不宜盲目重启。

异步删除也会影响观察结果。UNLINK、过期删除和 FLUSHALL ASYNC 可能由后台线程逐步完成,短时间内内存不会瞬间回落。如果使用了主从复制,还要考虑副本重新同步、复制积压缓冲区和输出缓冲区对内存的临时影响。

大量短键反复创建删除,容易产生碎片。Redis 4.0 以上支持主动碎片整理:

redis-cli CONFIG GET activedefrag

redis-cli CONFIG GET active-defrag-*

主动碎片整理会消耗 CPU,适合低峰期逐步启用,并通过监控观察延迟变化。托管 Redis 是否开放该能力,以服务商标配为准。

五、持久化与复制带来的内存开销

RDB 和 AOF 都会影响内存观察:

redis-cli INFO persistence

RDB 保存需要 fork 子进程。数据量大时,fork 可能带来短暂内存峰值;如果操作系统启用写时复制且写入频繁,RSS 会明显上升。AOF 重写同样需要 fork,且重写期间的新写入会被缓冲。

复制相关缓冲也要单独看:

redis-cli INFO replication

重点包括 repl-backlog、slave 输出缓冲、复制状态和重新同步次数。如果副本频繁断开重连,backlog 和输出缓冲可能反复增长。给客户端输出缓冲设置限制时,要区分普通客户端、副本和 Pub/Sub 客户端,避免误伤复制链路。

六、客户端缓冲区和无界集合

Redis 不是一个键很大才占内存,大量小键、长列表、Hash、Set、Stream 同样会累积。业务侧要检查队列是否只有生产没有消费、Set 是否无限追加、缓存键是否包含用户 ID 或日期却缺少过期时间。

客户端缓冲可以通过 CLIENT LIST 观察:

redis-cli CLIENT LIST

重点看输出缓冲区、空闲时间和客户端名称。Pub/Sub 或监控工具长时间订阅但没有消费,会积累输出缓冲。生产环境建议给应用连接设置名称,便于定位来源。

哈希、列表、集合的编码阈值也会影响内存。数据量较小时使用紧凑编码,超过阈值后转为标准结构,内存增长呈台阶状。不要为了省内存盲目调高编码阈值,还要同时评估读写延迟和命令复杂度。

七、推荐排查顺序

  1. INFO memory 记录 used_memory、RSS、碎片率和 maxmemory。
  2. INFO keyspace 判断键数量和过期键比例。
  3. 低峰期用 --bigkeys--memkeys 找大键,用 MEMORY USAGE 确认。
  4. 检查 maxmemory-policy 是否符合数据定位。
  5. 检查持久化 fork、AOF 重写和复制缓冲。
  6. 结合业务写入速率、命中率和系统内存曲线判断是否扩容。

扩容前至少保留一份 RDB 或托管备份。对于重要实例,不要直接清空数据;缓存类数据可以先按业务前缀分批删除,观察服务错误率和命中率。

八、验证与预防

处理后要看趋势,不是只看一次数值:

  • used_memory 回到预期区间,或增长速率与业务一致。
  • used_memory_rss 与碎片率逐步回落。
  • 键数量和过期键比例恢复正常。
  • 命令延迟、连接数、命中率没有恶化。
  • 系统层面没有 swap、OOM 或容器内存重启记录。

预防上,给缓存键统一设置 TTL;为队列和集合设置长度或消费监控;Redis 实例配置内存告警和 maxmemory 告警;持久化与复制缓冲纳入监控;上线前评估大 key 和热 key。清理脚本要先在测试环境验证,并限制 SCAN 批量大小。

结论

Redis 内存升高要先把数据增长、碎片、持久化 fork、复制缓冲和客户端缓冲拆开看。缓存类实例优先检查 TTL 和淘汰策略,存储类实例不要配置 allkeys 淘汰;删除后 RSS 不下降时,先确认 used_memory 是否下降,再考虑碎片整理。数据确实增长时,扩容前完成键归属、大 key 和备份检查,避免只把问题推迟到更大的内存规格。

参考资料

Redis 文档:INFO command
https://redis.io/docs/latest/commands/info/

Redis 文档:MEMORY USAGE
https://redis.io/docs/latest/commands/memory-usage/

Redis 文档:redis-cli –bigkeys
https://redis.io/docs/latest/tools/redis-cli/

Redis 文档:Eviction policy
https://redis.io/docs/latest/develop/reference/eviction/

Redis 文档:Client output buffers
https://redis.io/docs/latest/develop/reference/clients/

Redis 文档:Persistence
https://redis.io/docs/latest/develop/persistence/

实操指南知识库

Linux 服务器 CPU 飙高但网站还能打开?定位 Java、PHP、Nginx 与内核占用

2026-9-14 15:57:12

知识库

iptables与nftables核心概念入门:图解Linux网络包过滤的底层逻辑、表(Tables)与链(Chains)

2025-5-29 14:08:06