Redis 内存碎片

本文将介绍内存碎片的概念,说明 Redis 为什么会产生内存碎片,并介绍如何处理。

一、什么是内存碎片?

内存碎片是指内存中小且不连续的内存空间。

内存碎片的空间过小,导致它们无法被应用程序申请利用,但它们又实际占用了内存空间,因此会影响内存的使用率。

二、Redis 的内存碎片

Redis 中内存碎片出现的原因主要有:

  • 操作系统的内存分配机制
  • 键值对的增删改查

1. 操作系统的内存分配机制

内存分配器并不会完全按照应用程序申请的内存空间分配,而是按固定大小分配内存。

这种分配方式的目的是为了减少分配次数。

例如应用程序需要 20 个字节的空间,直接分配 32 个字节,当应用还需要写入 5 个字节时,不再需要二次分配

在这种分配机制下,Redis 会在每次申请都会获得更大一些的内存空间,使其 “占据” 一部分暂时不会使用的空间。

2. 键值对的增删改查

键值对的增删改查会导致空间的扩容和释放,在这一过程中,便可能导致内存中出现许多不连续的内存碎片。

三、Redis 内存碎片判断

Redis 支持查询内存使用的详细情况:

1
2
3
4
5
6
7
8
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_ratioused_memory_rssused_memory 相除的结果。其中, used_memory_rss 是操作系统实际分配给 Redis 的物理内存空间, used_memory 是 Redis 为了保存数据实际申请使用的空间。

  • mem_fragmentation_ratio 大于 1 但小于1.5 是合理的
  • mem_fragmentation_ratio 大于 1.5 时,表示内存碎片率已经超过 50%,应该采取措施降低内存碎片率

四、Redis 内存碎片处理

1. 重启 Redis 实例

一个简单粗暴的做法是重启 Redis 实例。

这个方法的后果是:

  • 如果 Redis 中的数据没有持久化,数据会丢失
  • 即使 Redis 中的数据已持久化,重启后也需要恢复时间

2. 内存碎片自动清理

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

这个方法简单来说就是 “搬家让位,合并空间”。

需要注意的是:碎片清理是有代价的。

碎片清理时需要拷贝数据、释放空间,这会带来时间开销。Redis 是单线程,数据拷贝将会影响 Redis 对请求的处理。

可以通过设置与内存碎片自动清理的参数,在适时碎片清理的同时避免对 Redis 的性能影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启用自动内存碎片清理
config set activedefrag yes

# 内存碎片的字节数达到 100MB 时,开始清理
active-defrag-ignore-bytes 100mb

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

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

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

参考