用户空间(user space)进程无法直接执行内核代码或者访问内核函数来分配内存资源,需要通过 系统调用接口 brk/sbrk (),请求系统内核来操作

系统调使 CPU 从用户态(user mode)切换到内核态(kernel mode),在需要频繁申请、释放内存的使用场景下会带来较大性能开销

为尽量减少 brk/sbrk () 的调用次数,内存管理函数 malloc/free () 在实现上做了一定的优化

一般 free () 释放内存时不降低 programe break 位置,而是将需要释放的内存添加到 空闲内存列表 ,供 malloc () 函数后续循环使用

malloc () 申请内存时优先在空闲内存列表查找>= 申请大小的内存块,直接返回 or 分割 or brk/sbrk

Redis 内存的管理机制依赖于 jemalloc/tcmalloc 等内存分配器(allocator)。删除 、清除过期 keys 等操作时调用 free () 函数释放内存可能并没有及时返还给操作系统,而是由内存分配器继续持有

Redis 可能会持有大量分配了却没有使用的内存空间,这部分空间被称为 内存碎片

内存碎片无法完全避免,只能降低碎片率

Redis 的内存碎片情况可以通过 INFO MEMORY 命令查看

redis memory 命令

4.0 前 info memory 只能查看 redis 内存大体使用状况,无法了解内存具体使用细节,比如 expire的消耗client output buffer, query buffer

Memory 是 Redis4.0 新特性,可用于分析详细内存使用情况,内存使用诊断,内存碎片回收等工作

memory help
help memory

info memory

# Redis 保存数据申请的内存空间
used_memory:
used_memory_human:

# 操作系统分配给 Redis 进程的内存空间 (used_memory_rss<used_memory可能是发生SWAP了)
used_memory_rss:
used_memory_rss_human:

# Redis 进程在运行过程中占用的内存峰值
used_memory_peak:
used_memory_peak_human:

# 内存碎片率,used_memory_rss / used_memory   (一般> 1.5 说明碎片过多需要清理了)
mem_fragmentation_ratio:

# Redis 最大可用内存,0表示不限制 (数据超出内存限制时执行 LRU 等删除策略)
maxmemory:0
maxmemory_human:0B

# 内存分配器
mem_allocator:jemalloc-5.x.x

内存碎片

9 字节内存空间, 1、2、3、5、6、9 已使用,如果计划申请 3 字节连续内存空间,按照现有内存使用情况无法申请, 4、7、8 就是 “内存碎片” 了

Redis 内存碎片主要如何形成

如何释放内存

重启 redis

生产忽略之?

备用实例同步后替换

思路通,但操作流程复杂且风险高

memory purge 手动碎片整理

阻塞主进程,生产环境慎用

memory purge 和 activedefrag 回收的并不是同一块区域的内存,它简单粗暴的尝试清除脏页以便内存分配器回收。可以根据实际情况和 activedefrag 配合使用,memory purge 在极端情况下效果较好,activedefrag 则更彻底

activedefrag 自动碎片整理

activedefrag 默认关闭,计划清理碎片时需手动开启

config set activedefrag yes

配置项归类为三类,功能开关、碎片的整理力度、资源使用情况

功能开关

整理力度

资源占用

清理时机

mem_fragmentation_ratio > 1.5 时,建议开始清理内存碎片

也可以通过分析调整 activedefrag 参数配置从而达到自动清理效果

正常情况下尽量保持禁用状态

redis activedefrag

核心是利用 jemalloc 特性,不从线程缓存中获取内存,重新申请一块内存,从而将旧的有内存碎片的内存释放掉