确认Redis Module吃内存需三步:先看used_memory_rss_human显著大于used_memory_human且mem_fragmentation_ratio正常,再查INFO modules非空,最后对比重启前后used_memory_peak_human是否加载Module后飙升不回落。

怎么确认是Redis Module在吃内存
Module本身不暴露独立内存统计,但会混在 used_memory 里——你看到 INFO memory 中 used_memory_human 持续上涨、evicted_keys 开始跳变,而 redis-cli --bigkeys 扫不出明显大 key,memory usage 查单个 key 也都很小,这时候就要怀疑 Module。
关键线索有三个:
-
used_memory_rss_human明显大于used_memory_human(比如差 1GB+),且mem_fragmentation_ratio正常(1.0–1.2),说明不是碎片问题,而是“看不见的内存”被占了 -
INFO modules返回非空(哪怕只有一行),表示已加载 Module;若返回(empty array),可直接排除 - 对比重启前后
used_memory_peak_human:加载 Module 后首次写入就飙升,且不随 key 清理回落,大概率是 Module 内部缓存或索引结构在驻留
如何查看具体 Module 的内存占用
Redis 7.0+ 原生支持模块级内存统计,低版本需依赖 Module 自身实现。先运行:
redis-cli INFO modules
如果输出包含 memory_usage 字段(如 redisearch、redisjson 6.2+、redismodule 2.0+),直接看该值;否则只能间接推断:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 对
redisearch:执行FT.INFO <index_name>,关注inverted_sz_mb、vector_index_sz_mb等字段 - 对
redisjson:用JSON.DEBUG MEMORY <key>查单个 JSON 值实际开销,再结合 key 数量估算总量 - 对自研 Module:检查其文档是否提供
MODULE LIST后的额外命令(如MYMODULE.MEMSTAT),或翻源码找RedisModule_Alloc/RedisModule_Calloc调用点
注意:MEMORY USAGE 对 Module 创建的复合结构(如 Search index、JSON document)通常返回 0 或远低于真实值,不能信。
Module 导致淘汰的典型配置陷阱
很多 Module 默认开启后台索引构建或缓存预热,它们不走 Redis 的 LRU 逻辑,却共享 maxmemory 配额——结果就是:key 没被淘汰,但 Module 缓存撑爆内存,触发全局淘汰。
-
redisearch的MINIMUM_TERM_LEN设太小(如 1),导致倒排索引爆炸式增长 -
redisjson的JSON.SET配合INDENT或NEWLINE选项,使内部 AST 结构冗余膨胀 - 未关闭
redisgraph的GRAPH.CONFIG SET RESULTSET_SIZE,导致查询缓存无限累积 - 所有 Module 共同风险:用
CONFIG SET动态修改参数后未持久化到redis.conf,重启即恢复高内存模式
监控 Module 内存必须做的三件事
靠人工查 INFO modules 不可持续。生产环境必须落地自动化监控:
- 每 30 秒采集一次
INFO memory和INFO modules,计算used_memory_human与各 Module 已知内存字段的差值,异常波动立即告警 - 对已知高风险 Module(如
redisearch),单独部署定时任务跑FT.INFO并聚合inverted_sz_mb + vectors_sz_mb,画趋势图 - 在 Prometheus + Redis Exporter 环境中,确保启用
--redis.metrics-keys=modules参数,否则 exporter 会跳过 Module 指标
最容易被忽略的是:Module 的内存增长往往是阶梯式的——比如批量导入数据时索引重建,一次涨 500MB,之后维持不动。这种“静默增长”不会触发 evicted_keys 实时跳变,但会让 used_memory_peak_human 持续抬高,直到下次写入才突然触发淘汰。必须盯住峰值,而不是当前值。

















