1.什么是内存碎片
当操作系统内存充足,但是却无法申请连续N字节内存空间时,这些剩余的内存空间就叫内存碎片。
2.内存碎片是如何形成的
内存碎片的形成有两方面的因素,第一个是分配策略,第二个是数据本身的修改,分别来看下。
2.1:分配策略
Redis使用的内存分配器,如jemelloc,在进行内存分配时并非需要多少就申请多少,而是按照2的次方来申请的,比如需要的是6字节的内存空间,则会申请8字节的,需要的是13字节则会申请16字节,而这比实际需要的多出的内存空间,就会形成内存碎片。如下图:
其中的红色区域就是内存碎片。
2.2:数据本身的修改
我们假定应用A和应用B分别申请了8字节和16自己的内存,然后应用A删除了3字节的数据,则此时就会出现3字节的内存碎片,如下图:
3.如何判断是否有内存碎片
可以通过info memory命令查看,如下:
127.0.0.1:6379> info memory
# Memory
used_memory:793320
...
used_memory_rss:956392
...
mem_fragmentation_ratio:1.2
mem_allocator:jemalloc-3.6.0 # 使用的内存分配器(自己加的)
以上used_memory代表实际使用的内存量,used_memory_rss代表实际分配的内存量,mem_fragmentation_ratio是used_memory_rss/used_memory,正常该值应该处于1~1.5之间,如果是大于1.5则说明内存碎片过于严重,需要进行干预处理。
mem_fragmentation_ratio值当出现小于1的情况时,则说明申请的内存不足够使用,而发生了swap,此时因为会有磁盘IO的发生,所以可能会导致响应速度变慢,需要加大内存。
4.如何清理内存碎片
清理内存碎片最直接的方法就是重启,该方法虽然简单粗暴,但也最简单有效,效果最好,实际工作中如果业务允许也可以使用该方法,但是如果是业务不允许该怎么办呢?在redis4版本中,就提供了碎片自动清理的机制,通过数据移动,空间合并等方法来达到内存碎片清理的目的,这个过程可以参考下图:
需要注意,碎片整理过程中是无法对外提供服务的,因为此时主线程需要拷贝数据,所以对这个时间我们需要进行控制,不能过长。首先想要开启内存碎片整理的话,需要配置 config set activedefrag yes,然后当满足如下条件时开始进行清理:
active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理;
active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理。
为了控制对Redis性能的影响,提供了如下参数控制清理操作占用的CPU时长:
active-defrag-cycle-min 25: 表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展;
active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。
如果你使用的是Redis4及以上的版本,可以在生产环境将这个配置使用起来。