Redis内存碎片率太低该怎么办?

背景问题

偶然收到某客户问题“我的Redis内存碎片率很低在0.2左右,网上说会导致Redis性能变慢,我该咋办?”。

官方的计算Redis内存碎片率的公式如下:

mem_fragmentation_ratio = used_memory_rss / used_memory

即Redis向操作系统中申请的内存分配器分配的内存总量的比值,两者简单来讲

  • 前者是我们通过top命令看到的redis进程RES内存占用总量
  • 后者由Redis内存分配器(如jemalloc)分配,包括自身内存、缓冲区、数据对象等

两者的比值结果< 1表示碎片率低,> 1为高, 碎片率高的问题百度上海量文章有介绍,不多赘述,但碎片率低基本都归咎于使用了SWAP而导致Redis因访问磁盘而性能变慢。但,真的是这样吗?

验证

客户生产环境中

  • 禁用了SWAP
  • 数据量为60M左右
  • repl-backlog-size 即复制积压缓冲区配置为1G

所以我这边设置下vm.swappiness = 1将swap先关掉,设置repl-backlog-size=512M,再启个Redis空实例。

image.png

看下memory stats,由于没任何键、复制线程、客户端,所以数据对象占用内存、复制积压缓冲区、客户端相关buffer都为0;此时Redis内存分配器分配的内存总量是 863944(启动后初始内存量startup.allocated+初始元数据dataset.bytes),向操作系统申请的内存为2789376,碎片率为3.48。
image.png

给测试库启动个从库后,碎片率瞬间降为0.01;
image.png

看下实例配置,实际复制积压缓冲区大小与分配器内存分配值能对应上,都为512M;所以启动复制后,因为分配总内存变大但向操作系统申请的内存无太大变化,所以碎片率取值自然会骤降。
image.png

为什么此时Redis不向操作系统申请配置指定的512M内存?

答案是:只有在slave端初次建立复制/失连时才会真正向操作系统申请复制积压缓存;并且不是一次性向OS申请512M,而是按需使用;可以简单测试如下

模拟从库失联

从库执行debug命令模拟Redis夯死

image.png

给主库制造点压力

image.png

通过指定命令输出内存使用情况如下。

image.png

能看到复制积压缓冲区、复制客户端输出缓冲区逐渐消耗内存,但操作系统实际内存used_memory_rss并非一次性打满,而是按需增加

碎片率小于1跟数据量有无关系?

前面通过实验,可以知道碎片率低并非仅由SWAP导致,复制积压缓冲区等配置值过大、键值对象数据极小的情况下也会使比值降低;那么数据量变大会咋样?

持续灌入数据

image.png

可以看到used_memroyused_memory_rss 都会逐渐变大,内存碎片率取值将逐渐趋于1。

image.png

结论

  • Redis内存碎片率低并非只跟SWAP有关,生产环境通常建议禁用了SWAP。
  • 复制积压缓冲区配置较大、业务数据量较小的情况下极容易造成碎片率远低于1这是正常现象,无需优化或调整。
  • 通常将线上环境复制缓冲区的值repl-backlog-size设置的比较大,目的防止主库频繁出现全量复制而影响性能。
  • 随着业务数据量增长,Redis内存碎片率比值会逐渐趋于1.

你可能感兴趣的:(Redis内存碎片率太低该怎么办?)