Redis用久了难免遇到内存方面的困扰:明明数据量没有明显增长,used_memory却一路攀升;或者RDB持久化之后系统层面内存没有归还;又或者碎片率高得吓人却不知道从哪里下手。Redis从4.0开始内置了一个内存诊断工具——MEMORY DOCTOR,它像一个自动体检的医生,扫描实例当前状态后直接给出一份诊断建议清单。很多人只知道它输出的第一行往往是“什么问题都没发现”,却不清楚其余提示的判断逻辑。本文把MEMORY DOCTOR的输出逐条拆解,并结合配套命令给出完整的诊断和优化路径。

一、MEMORY DOCTOR能诊断什么:输出项与判断阈值
MEMORY DOCTOR是一个只读命令,可以在redis-cli中直接执行。它不会做任何修改,只是根据INFO memory和MEMORY STATS的数据,按照内置的规则集给出建议。输出是若干条以提示形式呈现的文字,每一条对应一类内存问题。
127.0.0.1:6379> MEMORY DOCTOR Sam, I detected a few issues in this Redis instance memory implants: * Peak memory: In the past this Redis instance used more than 150% the memory that is currently used... * Client buffers: 1 clients are using more than 100KB of memory each...
它的判断规则大致包括以下几类,了解阈值才能知道触发了什么条件。第一类是碎片问题:当mem_fragmentation_ratio大于1.4且实例使用内存超过100MB时,会建议检查是否可以开启Active Defrag(主动碎片整理),或者确认maxmemory设置是否远大于实际数据量导致allocator大量囤积内存。第二类是峰值内存问题:如果历史峰值超过当前内存的150%,说明实例曾经历过一次内存高峰后又回落,可能存在大key删除、批量导入、过期风暴等场景,工具会提示用MEMORY STATS去分析数据集字节数与实际数据量的关系。
第三类是复制积压缓冲区与客户端缓冲区问题:如果普通客户端或从库类型的客户端输出缓冲区占用超过一定规模,DOCTOR会提示有客户端正在使用过多内存,通常是某个订阅客户端消费过慢,或某个从库同步滞后导致主库为其堆积大量输出数据。第四类是大key倾向:当数据集字节数除以key数量得到的平均每key字节数超过1024时,会建议做key采样分析,可能存在大对象。最后如果什么问题都没有,输出就是一句表示当前内存状态健康的提示语。
二、配合MEMORY STATS与INFO memory做精确定位
DOCTOR给出的只是方向性建议,真正定位问题需要借助MEMORY STATS命令。它返回的字典包含详细的内存构成:其中dataset.bytes表示实际数据集占用,clients.normal和clients.slaves分别表示普通客户端与从库连接的缓冲区内存,replication.backlog是复制积压缓冲区大小,total.allocated是allocator分配的总内存。把这些值和used_memory_rss对比,就能算出碎片到底占用了多少空间。
举个例子,如果DOCTOR提示客户端缓冲区问题,可以先用CLIENT LIST查看每个连接的omem字段(输出缓冲区内存),找出占用最大的连接。常见原因是pub/sub订阅者处理慢导致消息在输出缓冲区堆积,解决办法是给客户端输出缓冲区设置硬限制:
# 对订阅客户端:64MB硬限制,16MB后持续32秒则断开 client-output-buffer-limit pubsub 64mb 16mb 32 # 对从库连接:256MB硬限制,64MB后持续60秒则断开 client-output-buffer-limit replica 256mb 64mb 60
如果问题是碎片率过高,先分清两种情况:一是used_memory_rss大于used_memory很多,这是真正的碎片或allocator未归还内存;二是恰好相反,那多半是发生了swap,问题更严重。针对前者,Redis 4.0以上如果构建时带了jemalloc支持,可以开启主动碎片整理:
# 动态开启主动碎片整理 config set activedefrag yes # 碎片带来的额外内存超过100MB且碎片率超10%时开始整理 config set active-defrag-ignore-bytes 100mb config set active-defrag-threshold-lower 10 config set active-defrag-threshold-upper 100 config set active-defrag-cycle-min 5 config set active-defrag-cycle-max 75
需要注意,主动整理会占用CPU,线上开启建议从较小的cycle-min开始观察。此外还可以考虑换用内存效率更高的编码,例如小哈希使用ziplist(7.0后为listpack)结构,把hash-max-ziplist-entries和hash-max-ziplist-value设置在合理区间,能显著降低小对象的开销。
三、大key治理与长期内存管理建议
当DOCTOR提示平均每key字节数偏高时,就要做大key排查。Redis 4.0提供了MEMORY USAGE命令,可以精确计算单个key占用的内存,配合SCAN做增量遍历即可定位大key,避免使用会阻塞主线程的KEYS命令。
# 快速采样发现大key(按各类型最大值统计,-i控制采样间隔避免压垮实例) redis-cli --bigkeys -i 0.1 # 按内存占用采样,更贴合内存诊断场景 redis-cli --memkeys -i 0.1 # 精确测量单个key的内存占用,SAMPLES 0表示完整计算 redis-cli MEMORY USAGE mykey SAMPLES 0
找到大key后的处理策略要分场景:如果是缓存类的大value,考虑拆分成多个小key,或者压缩后再存储;如果是集合类大key,用SCAN配合批量删除慢慢清空,Redis 4.0也提供了UNLINK命令替代DEL,让释放动作在后台线程执行,避免阻塞主线程。删除后如果碎片率仍高,可以配合MEMORY PURGE命令主动向jemalloc申请归还空闲内存,不过实际效果取决于allocator的实现。
从长期管理角度看,内存优化不能只依赖事后诊断。建议做好这几件事:合理设置maxmemory并配好淘汰策略,让实例有明确的水位线;将used_memory_peak纳入监控告警,峰值异常往往意味着业务上存在批量写入或大key操作;在业务低峰期定期执行MEMORY DOCTOR作为巡检项,把输出接入运维脚本做趋势对比。诊断工具给方向,MEMORY STATS给细节,采样命令给证据,三者结合才是完整的Redis内存优化闭环。
RedisMEMORY DOCTOR内存优化修改时间:2026-09-02 10:45:03