文章目录

  • 内存碎片
  • 形成原因
  • 内因:内存分配器的分配策略
  • 外因:键值对大小不一样和删改操作
  • 判断是否有内存碎片
  • 清理内存碎片
  • 重启Redis实例
  • Redis自动清理



数据删除后,Redis释放的内存空间会由内存分配器管理,不会立即返回给操作系统

风险点:Redis释放的内存空间不是连续的,不连续的内存空间很有可能会处于一种闲置的状态。降低机器的成本回报率

内存碎片

可以类比高铁车厢座位,比如5个人出游,但是现在买票的时候发现当前车次每个车厢都留了两个位置,但是你们想5个人坐一起聊天,没有连续的座位,所以没办法就换了一辆车次,这样分散的空座位就空闲了。

redis 删除pubsub redis 删除数据还存在_内存空间


操作系统的额内存碎片原理类似,操作系统的剩余内存空间足够,但是应用申请的是一块连续的N字节内存空间,但是没有连续的N字节的剩余内存空间了,这些剩余空间就是内存碎片。

形成原因

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

内存分配器一般是按照固定大小来分配内存,不是完全按照应用程序申请的内存大小给程序分配。

Redis可以使用libc、jemalloc、tcmalloc多种内存分配器来分配内存,默认使用jemalloc。

jemalloc是按照一系列固定的大小划分内存空间,例如8字节、16字节、32字节、48字节等,当程序申请的内存最接近某个固定值时,jemalloc就会给它分配相应的大小空间。

这样的分配方式可以减少分配次数,比如申请了20个字节的空间保存数据,jemalloc会分配32字节,如果还需要写入10字节的数据,那么就不用重新申请空间了

Redis每次向分配器申请的内存空间大小不一样,这样分配方式就会有内存碎片形成的风险。

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

Redis通常作为共用的缓存系统或键值对数据库对外提供服务,不同业务应用保存的数据会带来大小不同的键值对,分配的空间大小不一,这样就会造成一定的碎片,降低内存的存储效率

redis 删除pubsub redis 删除数据还存在_Redis_02


键值对修改或删除会导致空间的扩容和释放

判断是否有内存碎片

通过Redis自身命令INFO memory 来查看mem_fragmentation_ratio指标
计算公式:

mem_fragmentation_ratio=used_memory_rss/ used_memory
  • used_memory_rss:操作系统时机分配给Redis的物理内存空间,包含了碎片
  • used_memory:为了保存数据实际申请使用的空间

经验判断

  • 1<mem_fragmentation_ratio<1.5:内存的分配器策略和Redis本身存储特性,碎片是正常的
  • mem_fragmentation_ratio>1.5:说明碎片率超过了50%,需要采用一些措施了

清理内存碎片

重启Redis实例

  • Redis的数据没有持久化,就会丢失
  • 即使持久化了,需要AOF或RDB进行恢复,恢复时长取决于AOF或RDB大小

Redis自动清理

主要思想为搬家让位,合并空间
当有数据把一块连续的内存空间分割成好几块不连续的空间时,操作系统就会把数据拷贝到别处。此时,数据拷贝需要能把这些数据原来占用的空间都空出来,把原本不连续的内存空间变成连续的空间

如下:

redis 删除pubsub redis 删除数据还存在_redis 删除pubsub_03


碎片清理是有代价的

  • 时间开销:操作系统需要把多份数据拷贝到新位置,把原有空间释放出来。
  • 阻塞开销:因为 Redis 是单线程,在数据拷贝时,Redis 只能等着,这就导致 Redis 无法及时处理请求,性能就会降低。
  • 顺序开销:有的时候,数据拷贝还需要注意顺序,就像刚刚说的清理内存碎片的例子,操作系统需要先拷贝 D,并释放 D 的空间后,才能拷贝 B。这种对顺序性的要求,会进一步增加 Redis 的等待时间,导致性能降低。

通过Redis设置自动内存碎片清理参数,来控制碎片清理的开始和结束时机,以 及占用的 CPU 比例,从而减少碎片清理对 Redis 本身请求处理的性能影响。

启用了自动清理功能

//
config set activedefrag yes

触发内存清理需要满足的两个条件

  • active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理;
  • active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理。

为了尽可能减少碎片清理对 Redis 正常请求处理的影响,自动内存碎片清理功能在执行时,还会监控清理操作占用的 CPU 时间,而且还设置了两个参数,分别用于控制清理操作 占用的 CPU 时间比例的上、下限,既保证清理工作能正常进行,又避免了降低 Redis 性 能。这两个参数具体如下:

  • active-defrag-cycle-min 25: 表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展;
  • active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致 响应延迟升高。当清理影响性能的时候建议调小 active-defrag-cycle- max 的值,以减轻对正常请求处理的影响。

自动内存碎片清理机制在控制碎片清理启停的时机上,既考虑了碎片的空间占比、对 Redis 内存使用效率的影响,还考虑了清理机制本身的 CPU 时间占比、对 Redis 性能的影 响。

清理机制还提供了 4 个参数,让我们可以根据实际应用中的数据量需求和性能要求灵活使用