

Redis内存碎片:深度解析与优化策略
source link: https://www.51cto.com/article/769661.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在我们探究和优化Redis性能的过程中,「Redis内存碎片」是一个不可忽视的话题。
这篇文章将深入研究这个看似微不足道,但实际上对Redis运行效率产生重要影响的问题。首先,让我们揭开Redis内存碎片的神秘面纱,理解它的本质及其为何成为我们必须面对的挑战。

内存碎片如何产生的
Redis内存碎片主要是因为Redis数据存储和回收过程中的内存管理问题导致的。
Redis分配内存时,会根据需要申请一段连续的内存空间。但当Redis删除或修改数据时,释放的内存空间并不一定能被立即重新利用,尤其是当这些空闲内存空间大小不一致时,就可能导致内存碎片的出现。
为了提高内存使用的效率,Redis内部使用内存分配器来对内存的申请和释放进行管理。Redis使用的内存分配器默认是「jemalloc」。
而内存分配器是按照固定大小来分配内存的,并不是完全按照程序申请的内存大小来进行分配。
比如程序申请一个20字节的内存,内存分配器会分配一个32字节的内存空间,这么做是为了减少分配次数。redis会申请不同大小的内存空间来存储不同业务不同类型的数据,由于内存按照固定大小分配且会比实际申请的内存要大一些,这个过程中会产生内存碎片。
举个生活中的例子,帮助大家理解:
假设你正在整理一间图书馆。图书馆的书架就像是Redis储存数据的内存空间。每本书都代表不同大小的数据。刚开始时,你把所有的书都按照大小放好。小书在一侧,大书在另一侧。这样你可以有效地利用书架的空间,也方便找书。
但是,如果你需要移除一些书(删除某些数据),然后又加入新的书(新增数据),就可能出现问题了。例如,你移除了一些大书,把它们的位置空出来,然后把新的小书放进去。这样下来,原本属于大书的空间,现在只被小书部分占用,剩余的空白就成了“内存碎片”。
又或者你有一堆新的大书要放,但书架上只有分散的小书的空位,无法容纳这些大书。这个时候你可能需要重新排列整个书架(类似于Redis的内存整理)去腾出连续的大片空间来摆放这些新的大书。
总结来说:当数据不断删除和新增时,内存中空出的位置可能无法完全匹配新数据的大小,导致产生未被利用的“碎片”空间,这就是内存碎片。
内存分配器
Redis 使用内存分配器来管理其在运行期间需要使用的内存资源。可以是libc、jemalloc、tcmalloc。默认是jemalloc。
要指定 Redis 使用哪个内存分配器,你需要在编译 Redis 时做出选择。通常在执行 make 命令时可以通过 MALLOC 参数来指定。例如,如果你想使用 jemalloc,你可以像这样编译 Redis:make MALLOC=jemalloc。
jemalloc在64位系统中,将内存空间划分为小、大、巨大三个范围。每个范围内又划分了许多小的内存块单位,存储数据的时候,会选择大小最合适的内存块进行存储。
jemalloc划分的内存单元如下图所示:

也就是说Redis是以指定大小的块为单位进行连续内存分配的,而不是按需分配的,Redis 会根据申请的内存最接近的固定值分配相应大小的空间。
这就像你有不同的箱子,为了装东西,你需要找一个体积最接近的箱子来装。但是装进去后,你发现还有空间可以放一些小东西,就无需再找箱子了。
但是,这种分配空间的方式会带来一定程度的内存碎片。我们可以把固定大小的划分空间看成不同体积的箱子,每种箱子里的空间不同程度上都会有剩余。这些剩余的空间就是内存碎片。
怎么看是否有内存碎片
我们登陆到Redis服务器上,执行以下命令,这会返回一段描述Redis内存使用情况的文本。
redis> info memory
我们会看到类似如下的信息:

在这里,我们主要关注的是名为mem_fragmentation_ratio的字段,它显示了Redis内存碎片的比例。
如果mem_fragmentation_ratio大于1,那就表示存在内存碎片。这个值越大,内存碎片就越多。如果该值非常接近1或者小于1,则表示内存碎片很少或者没有。
计算公式为:
mem_fragmentation_ratio = used_memory_rss / used_memory
- used_memory_rss:代表Redis进程占用的总物理内存大小(包括码区、数据区和堆栈等),单位是字节。
- used_memory:代表Redis分配器申请的内存总量,也就是从操作系统角度看进程实际使用的虚拟内存空间,单位是字节。
碎片率的意义
mem_fragmentation_ratio的不同值,说明不同的情况。
- 大于1:说明内存有碎片,通常在1到1.5之间是正常的。
- 大于1.5:说明内存碎片率比较大,需要考虑是否要进行内存碎片清理,要引起重视。
- 小于1:说明已经开始使用交换内存,也就是使用硬盘了,正常的内存不够用了,需要考虑是否要进行内存的扩容,使用swap是相当影响性能的。
清理内存碎片
1.低于4.0-RC3版本的Redis
Redis 4.0-RC3之前的版本并没有内置的内存碎片整理工具。如果你想要清理内存碎片,可以通过重启的方式。
当Redis重新启动时,它会通过RDB持久化功能将数据存储到磁盘,然后再从磁盘加载数据到内存,这个过程可以有效地清理内存碎片。但这种方法会导致服务的临时中断。
2.高于4.0-RC3版本的Redis
Redis4.0-RC3版本开始,引入了active-defrag 特性。可以在不重启的情况下,自动进行碎片清理。
开启配置如下,此选项的默认值是关闭的,激活碎片整理可能会占据一些 CPU 时间。
redis> config set activedefrag yes
注意:自动清理内存碎片的功能需要该Redis的内存分配器是jemalloc时才能启用。
启用后需要同时满足下面2个参数的设置条件时才会触发自动清理:
active-defrag-ignore-bytes 100mb # 默认100MB,表示内存碎片空间达到100MB时
active-defrag-threshold-lower 10 # 默认10,表示内存碎片空间占OS分配给redis的物理内存空间的比例达到10%时
redis是单进程模型,内存碎片自动清理是通过主线程操作的,也会消耗一定的CPU资源。为了避免自动清理降低Redis的处理性能,如下两个参数可以控制清理动作消耗的CPU时间比例的上下限:
active-defrag-cycle-min 5 # 默认5,表示自动清理过程所用 CPU 时间的比例不低于5%,保证清理能正常开展;
active-defrag-cycle-max 75 # 默认75,表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。
如果你对自动清理的效果不满意,可以使用如下命令,直接进行手动碎片清理:
redis > memory purge
需要注意的是,该命令会阻塞主进程,并且目前也仅实现了jemalloc作为内存分配器的内存统计,对其他分配器暂不支持。
本篇文章到这就结束了。在我们深入研究Redis内存碎片管理和优化策略后,可以明确一点:理解并合理处理内存碎片化对于保证Redis的性能及稳定性至关重要。
不论是进行内存分配策略的调整,还是使用适当的数据结构,都是对Redis内存管理的优化。
同时,定期的监控和审视也是必不可少的步骤。希望本文能为你在处理Redis内存碎片问题上提供一些有价值的启示。记住,每一个优秀的工程师都应该以理解其使用的工具为荣。让我们持续关注和优化Redis,使其更好地服务于我们的项目,推动业务的发展。
Recommend
-
137
一种避免 iOS 内存碎片的方法修改于2017-10-24 01:39:55阅读 1.5K0在和服务器传输文本的时候,可能会因为某一个字符的编码格...
-
28
本文出现的内核代码来自Linux4.19,如果有兴趣,读者可以配合代码阅读本文。 一、Linux物理内存外碎片化概述 什么是Linux物理内存碎片化?Linux物理内存碎片化包括两种: 1.物理内存内碎片:指...
-
7
Linux 内核 VS 内存碎片 (下)TiDB Robot开源分布式数据库 TiDB从
-
10
Redis 数据结构与内存管理策略(上) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 作者:王清培(Plen wang) 沪江Java资深架构师 Redis 数据类型特点与使用场景 String
-
9
Redis作为一个成熟的数据存储中间件,它提供了完善的数据管理功能,比如之前我们提到过的数据过期和今天我们要讲的数据淘汰(evict)策略。在开始介绍Redis数据淘汰策略前,我先抛出几个问...
-
7
文章首发于公众号 “蘑菇睡不着”《源码级别了解Redis持久化》 《聊聊Redis过期键删除策略》
-
4
二:Redis配置文件redis.conf中关于AOF的相关配置 ############################## APPEND ONLY MODE ############################### # By default Redis asynchronously dumps the dataset on disk. This mode is # g...
-
12
Redis系列11:内存淘汰策略
-
9
缓存过期策略 定时删除 没人用 含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除 优点:该策略可以立即清除过期的数据, 保证内存被尽...
-
9
Redis内存兜底策略——内存淘汰及回收机制 Redis内存淘汰及回收策略都是Redis内存优化兜底的策略,那它们是如何进行兜底的呢?先来说明一下什么是内存淘汰和内存回收策略:...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK