RedisJSON 内存占用剖析与调优
一、基础内存模型
-
指针包装
- 所有 JSON 值(标量、对象、数组、字符串等)至少占用 8 字节,用于存储一个带类型标记的指针。
-
标量与空容器
null
、true
、false
、小整数(静态缓存)、空字符串、空数组、空对象 均不分配额外内存,仅用上述 8 字节指针指向静态实例。
二、字符串存储
-
额外字节消耗 = 字符串长度
-
示例:存储
"bar"
(3 字节)JSON.SET foo . '"bar"' JSON.DEBUG MEMORY foo → 11 字节(8 + 3)
三、数组的几何增长
-
初始容量:4
-
元数据:16 字节(8 字节容量,8 字节当前长度)
-
指针包装:8 字节
-
元素指针数组:
capacity × 8
字节 -
示例:
- 1–4 个元素 → 8 + 16 + 4×8 = 56 字节
- 第 5 个元素触发扩容至 8 → 8 + 16 + 8×8 = 88 字节
四、磁盘文件存储对比
测试文件 | 原始 JSON 大小 | RedisJSON 占用 | MessagePack 占用 |
---|---|---|---|
pass-100.json (380 B) | 381 B | 1,069 B | 140 B |
pass-jsonsl-1.json (1.4 KB) | 1,387 B | 2,190 B | 757 B |
pass-json-parser-0000.json (3.7 KB) | 3,718 B | 5,469 B | 2,393 B |
pass-jsonsl-yahoo2.json (22 KB) | 22,466 B | 26,901 B | 16,869 B |
pass-jsonsl-yelp.json (46 KB) | 46,333 B | 57,513 B | 35,529 B |
提示:删除数组或对象中的元素并不会自动释放已分配的内存。
五、全局字符串重用机制
- Redis 内核对相同字符串内容只存一份物理内存,多处引用。
JSON.DEBUG MEMORY
报告时仍按逻辑实例“各自”计算,可能显著高于实际物理占用。
六、调优建议
- 小字符串优先:尽量避免超长文本字段,或分割存储;
- 合理预分配数组:对大数组可预先
JSON.SET
一个空数组并扩容到合适长度,减少中间扩容次数; - 字段重用:对重复出现的关键字或枚举值,依赖 Redis 全局字符串重用降低物理占用;
- 监控内存:定期使用
JSON.DEBUG MEMORY
与MEMORY USAGE
对比物理报告,识别潜在内存膨胀; - 版本升级:关注新版 RedisJSON 的优化与内存改进,及时升级。
通过以上剖析与对比,您可以更精准地评估和控制 RedisJSON 在生产环境中的内存消耗,并制定高效的存储与访问策略。