Redis学习笔记20——删除数据后,为什么内存占用率还是很高?

在使用 Redis 时,或许会遇到这样一个问题:明明做了数据删除,数据量已经不大了,为什么使用 top 命令查看时,还会发现 Redis 占用了很多内存呢?

实际上,这是因为,当数据删除后,Redis 释放的内存空间会由内存分配器管理,并不会立即返回给操作系统。所以,操作系统仍然会记录着给 Redis 分配了大量内存。

但是,由于Redis释放的内存空间可能不是连续的,所以无法保存较大的数据。这将减少Redis能够保存的实际数据量,也会降低Redis运行机器的成本回报率。

内存碎片是如何形成的

内因:内存分配器的分配策略

jemalloc分配策略:
将内存划分成一系列固定大小的内存空间,操作系统会分配给大小最接近空间。比如需要20字节,会分配32字节的空间。如果以后需要增加数据(如大小10字节的数据)时不需要再次分配分配内存,减少时间消耗。但是如果以后不需要增加数据了,则会形成碎片。

外因:键值对大小不一样和删改操作

首先,Redis 申请内存空间分配时,本身就会有大小不一的空间需求。又因为内存分配器会分配一个稍微大些的内存空间,这样就会造成碎片。

其次,这些键值对会被修改和删除,这会导致空间的扩容和释放。具体来说,一方面,如果修改后的键值对变大或变小了,就需要占用额外的空间或者释放不用的空间。

判断是否有内存碎片及解决办法

是否有内存碎片

使用INFO memory可以监控实时的内存使用情况。

INFO memory
# Memory
used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G
…
mem_fragmentation_ratio:1.86

这里有一个 mem_fragmentation_ratio 的指标,它表示的就是 Redis 当前的内存碎片率。

mem_fragmentation_ratio  = used_memory_rss / used_memory

例如,Redis申请了100字节(used_memory),操作系统实际分配了128字节(used_memory_rss),则mem_fragmentation_ratio为1.28

一般来说mem_fragmentation_ratio > 1.5时,这时的内存碎片率超过了50%,就需要采取一些方法降低内存碎片率了。

mem_fragmentation_ratio < 1时发生了什么

mem_fragmentation_ratio小于1,说明used_memory_rss小于了used_memory,这意味着操作系统分配给Redis进程的物理内存,要小于Redis实际存储数据的内存,也就是说Redis没有足够的物理内存可以使用了,这会导致Redis一部分内存数据会被换到Swap中,之后当Redis访问Swap中的数据时,延迟会变大,性能下降。

如何清理内存碎片

简单粗暴的方法——重启Redis。
但是会有两个后果:

  • 如果 Redis 中的数据没有持久化,那么,数据就会丢失;
  • 即使 Redis 数据持久化了,我们还需要通过 AOF 或 RDB 进行恢复,恢复时长取决于 AOF 或 RDB 的大小,如果只有一个 Redis 实例,恢复阶段无法提供服务。

在 4.0-RC3 版本以后,Redis 自身提供了一种内存碎片自动清理的方法

Redis学习笔记20——删除数据后,为什么内存占用率还是很高?_第1张图片
不过碎片清理显然会带来性能上的损失,因为 Redis 是单线程,在数据拷贝时,Redis 只能等着,这就导致 Redis 无法及时处理请求,性能就会降低。

所以我们需要根据Redis提供的自动内存碎片清理参数,控制碎片清理的开始、结束、占用cpu比例,从而减少其对性能的影响。

自动内存碎片清理参数

1、如果要启动自动内存碎片清理,需要把activedefrag配置项设置为yes

config set activedefrag yes

2、active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理;

3、active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理。

4、active-defrag-cycle-min 25: 表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展;

5、active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。

这也是一个让Redis变慢的潜在风险

如果遇到了Redis变慢,可以通过日志,检查是否正在进行碎片清理。如果确实在进行碎片清理,可以调小active-defrag-cycle-max的值,以减轻对正常请求处理的影响。

你可能感兴趣的:(Redis学习笔记20——删除数据后,为什么内存占用率还是很高?)