Redis 的内存消耗

摘要:redis 的内存消耗,在优化 redis 的内存消耗之前,我们应该先搞懂 redis 的内存消耗在哪里,主要消耗在 reids 的自身内存,对象存储,内存缓冲,内存碎片上。

Redis 内存使用统计

可以在客户端执行命令 info memory 命令获取相关指标,以下是一些比较重要的属性。

127.0.0.1:6379> info memory
# Memory
used_memory:869256 # redis 分配器分配的内存总量,也就是内部存储的所有数据内存占有量
used_memory_human:848.88K # used_memory 的可读格式

used_memory_rss:16875520 # 从操作系统角度显示 reids 进程占用的物理内存总
used_memory_rss_human:16.09M # used_memory_rss 的可读格式

used_memory_peak:884280 # 内存使用的最大值,表示 used_memory 的峰值
used_memory_peak_human:863.55K # used_memory_peak 的可读格式

used_memory_lua:37888 # lua 引擎所消耗的内存大小
used_memory_lua_human:37.00K # used_memory_lua 可读格式

mem_fragmentation_ratio:20.38 # used_memory_rss/used_memory 比值 表示内存碎片率

mem_allocator:jemalloc-5.1.0 # redis 所使用的内存分配器,默认为 jemalloc

当 mem_fragmentation_ratio > 1 时,说明 used_memory_rss - used_memory 多出的部分内存并没有用于数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重。

当 mem_fragmentation_ratio<1 时,这种情况一般出现在操作系统把 redis 内存交换(swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,redis 性能会变得很差,甚至僵死。


Redis 的内存消耗划分(自身内存 + 对象内存 + 缓冲内存 + 内存碎片)

自身内存

redis 空进程自身内存消耗非常少,,通常 used_memory_rss 在 3mb 左右,used_memory 在 800kb 左右,一个空的 redis 进程消耗内存可以忽略不计。

对象内存

对象内存是 reids 内存占用最大一块,redis 采用键值存储,每创建一个对象至少包含两个类型对象 key 和 value。key 都是字符串,我们应该使用较短的 key 名来存储。value 主要包含五种类型,字符串,列表,哈希,集合,有序集合。

缓冲内存(客户端缓冲,复制积压缓冲区,aof 缓冲区)

客户端缓冲分为普通客户端,和从客户端两种。普通客户端是指连接 redis 服务器的 tcp 连接输入和输出缓冲,但是 redis并没有对普通客户端的输出缓冲区做限制,一般普通客户端的内存消耗可以忽略不计。从客户端,值得是主从复制中的从客户端,从服务最好不要多余 2 个,并且主从节点不要部署在较差的网络环境下,如异地跨机房环境,防止复制客户端连接缓慢造成溢出。

复制积压缓冲区,redis 提供了一个可重用的固定大小缓冲区用于实现复制功能,,根据 repl-backlog-size 参数控制,默认1mb。对于复制积压缓冲区整个主节点只有一个,所有的从节点共享此缓冲区,因此可以设置较大的缓冲区空间,如100MB,这部分内存投入是有价值的,可以有效避免全量复制。

aof 缓存区,这部分空间用于在 redis 重写期间无法保存最近写入的命令。aof 缓冲区空间消耗用户无法控制,消耗的内存取决于 aof 重写时间和写入命令量,这部分空间占用通常很小。

内存碎片

redis 默认内存分配器采用 jemalloc,可选的还有 glibc,tcmalloc 等。比如当保存 5 k 内存数据时,jemalloc 可能会分配给 8 k 的块存储,剩下的 3 k 就变成了内存碎片不能分配给其他对象存储。

产生内存随便主要是由于,频繁的更新操作,比如对已存在的键执行 append、setrange 等更新操作。或者大量过期键删除,键对象过期删除后,释放的空间无法得到充分利用,导致碎片率上升。


子进程的内存消耗

子进程内存消耗主要来源于 aof 或者 rdb 重写时 redis 创建的子进程内存消耗。redis 执行 fork 操作产生的子进程内存占用量对外表现为与父进程相同,理论上需要一倍的物理内存来完成重写操作。但 linux 具有写时复制技术(copy-on-write),父子进程会共享相同的物理内存页,当父进程处理写请求时会对需要修改的页复制出一份副本完成写操作,而子进程依然读取 fork 时整个父进程的内存快照。

thp 机制:开启 thp 机制会降低子进程 fork 速度,但是会导致复制的负担加重,如果在父进程有大量写操作的情况下,会加重内存的复制量,从而造成内存过度消耗,比如第一次复制内存页单位是 4 kb,下次就直接编程 2 mb了。

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top