为什么卸载了软件后还是内存不足


为什么卸载了软件后还是内存不足

使用 Redis 时,我们有时会遇到这样一个问题:明明已经删除了不少数据,但查看时仍发现 Redis 占用了很多内存。这是为什么呢?

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

这种情况往往伴随着一个潜在的风险:Redis 释放的内存空间可能并不连续,这些不连续的内存空间就会处于闲置状态。这会导致一个问题,即虽然有闲置空间,Redis却无法用来保存新的数据,这不仅会降低 Redis 能够实际保存的数据量,还会降低 Redis 运行机器的成本效益。

我们可以把 Redis 的内存空间比作高铁上的座位数来解释这一现象。如果高铁有很多座位,但乘客数量很少,那么高铁的运行效率就会降低,成本效益也会下降。同样,如果你租用了一台内存较大的云主机运行 Redis,但保存的数据量较小,那么你租用的成本效益也会降低。

这节课,我们就来探讨一下 Redis 的内存空间存储效率问题,并寻找解决方案。我们要了解为什么数据已经删除,但内存却闲置不用。

通常情况下,内存空间的闲置是由于操作系统发生了严重的内存碎片导致的。那么,什么是内存碎片呢?

为了帮助你理解,我们再回到高铁座位的例子。假设一个车厢有 60 个座位,现在只剩下 5 个空位。你和朋友想要坐在一起,但选座位时发现没有连续的空位了。你们只能换一辆车。这样,那辆车就有几个空座位闲置了。

这些空座位的大小和位置不连续,就像内存中的碎片一样。虽然操作系统的剩余内存总量足够,但应用需要的是一块连续的内存空间。在这块连续的空间中,没有足够大小的空间可供应用使用,这就形成了内存碎片。

Redis 中的内存碎片形成有内因和外因两个方面的原因。简单来说,内因是操作系统的内存分配机制,外因是 Redis 的负载特性。

内因方面,不同的内存分配器有不同的分配策略。例如,jemalloc 是按照一系列固定的大小来分配内存的。当应用申请的内存空间最接近某个固定值时,jemalloc 就会分配相应大小的空间。这种分配方式旨在减少分配次数,提高效率。但这也可能导致一定的内存碎片。

了解了造成内存碎片的内外因素后,我们可以通过 Redis 提供的 INFO 命令来查询内存使用情况,判断是否存在内存碎片问题。mem_fragmentation_ratio 指标可以帮助我们了解当前的内存碎片率。如果 mem_fragmentation_ratio 值大于 1 但小于 1.5,一般情况下是可以接受的。但如果大于 1.5,那么可能需要采取一些措施来降低内存碎片率了。

当 Redis 出现内存碎片时,一个直接的解决办法是重启 Redis 实例。但这并不是一个优雅的方法,因为重启会导致数据丢失和服务中断。幸运的是,从 4.0-RC3 版本开始,Redis 提供了一种自动清理内存碎片的机制。

自动清理内存碎片的机制简单来说就是“搬家让位,合并空间”。当有数据把一块连续的内存空间分割成不连续的空间时,操作系统会将数据拷贝到别处,释放出原本占用的空间,并将这些不连续的空间合并成连续的空间。这样就能够清理碎片,提高内存的实际利用率。

但是需要注意的是,碎片清理是有代价的。操作系绠需要把数据拷贝到新位置,这会带来时间开销。而且,数据拷贝还需要注意顺序性,这会增加 Redis 的等待时间,导致性能降低。

为了缓解这个问题,我们可以通过设置 Redis 的相关参数来控制碎片清理的时机和 CPU 占用比例。例如,我们可以启用自动清理功能,并设置触发清理的条件和 CPU 时间占比的上下限。这样可以在保证清理工作正常进行的避免对 Redis 的性能产生过大影响。

内存碎片并不可怕。我们需要做的就是了解它、重视它、并借助高效的方法解决它。通过合理使用自动清理机制和灵活调整相关参数,我们可以提高 Redis 的内存实际利用率、降低成本并提高收益。


为什么卸载了软件后还是内存不足