bigywater.tech
Redis · 17

Redis 内存碎片

插入20万个key再交替删除一半,对比used_memory和used_memory_rss的变化,看内存碎片是怎么在Redis进程里产生的。

1.14→2.07
交替删除前后的碎片率变化
used_memory减半
Redis自己统计的逻辑内存如期下降
rss不降反升
操作系统报告的物理内存没有归还

做的事:插入20万个key,再交替删除一半

used_memory是Redis自己统计的"逻辑上在用"的内存,used_memory_rss是操作系统报告的物理内存占用。

操作插入20万个key(值大小随机50~500字节) INFO memory | used_memory / used_memory_rss / mem_fragmentation_ratio 交替删除偶数下标的10万个key(每隔一个删一个) INFO memory | 再看一次

验证:插入完成后,碎片率是健康的

刚写满数据的时候,逻辑内存和物理内存贴得很近。

结果(插入20万个key之后)used_memory: 71461408 字节 (≈71.46MB) used_memory_rss: 77512704 字节 (≈77.51MB) mem_fragmentation_ratio: 1.14

1.14的碎片率是健康区间(一般认为1~1.5算正常)——物理内存比逻辑内存多了大约6MB,这部分是正常的分配器预留和元数据开销,不算浪费。

验证:删掉一半key之后,物理内存没有跟着降

按"每隔一个删一个"的方式删掉10万个key,制造的内存空洞。

结果(交替删除10万个key之后)DBSIZE: 100000(逻辑上只剩一半key了) used_memory: 37465536 字节 (≈37.47MB,几乎正好减半) used_memory_rss: 81051648 字节 (≈81.05MB,不降反升!) mem_fragmentation_ratio: 2.07(从1.14涨到2.07)

Redis自己统计的 used_memory 老老实实地减半了——逻辑上确实只剩10万个key在用内存。但操作系统报告的 used_memory_rss 一点没降,反而比删除前还高了一点。碎片率从1.14飙升到2.07,意味着"操作系统分配给Redis进程的物理内存"里,超过一半其实已经是没人在用的空洞。

原因是"交替删除"这种模式,在内存里留下的是大量分散的小空洞——底层内存分配器(jemalloc)虽然会把这些空间标记为"可以复用",但很少会主动把这批已经从操作系统那里申请到的物理内存页归还回去,尤其是当空洞分散在很多页面里、凑不成完整的空闲页时。这就是内存碎片的样子:不是"内存丢了",是"内存被占着,但logically没人在用,也还不了"。

分步演示:交替删除是怎么制造内存碎片的

每一步都是本文上面用INFO memory拿到的原始数字。

逻辑内存减半了,物理内存没有归还
这一步新验证的状态

    本文用到的工具

    • 本机 Redis 8.10.1 单节点,20万key,随机50~500字节value
    • INFO memory:对比used_memory / used_memory_rss / mem_fragmentation_ratio
    京ICP备2026067502号-1京公网安备11010502063487号