redis4.0下MEMORY命令详解

71次阅读
没有评论

共计 6843 个字符,预计需要花费 18 分钟才能阅读完成。

这篇文章主要介绍“redis4.0 下 MEMORY 命令详解”,在日常操作中,相信很多人在 redis4.0 下 MEMORY 命令详解问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”redis4.0 下 MEMORY 命令详解”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

前言

在过去,查看 redis 的内存使用状态只有 info memory 命令,而且也只有一些基础信息,想要获取全局信息就有些困难。4.0 开始 redis 提供了 MEMORY 命令,一切都变得简单起来。

MEMORY 命令

MEMORY 命令一共有 5 个子命令,可以通过 MEMORY HELP 来查看:

127.0.0.1:6379 memory help

1) MEMORY DOCTOR – Outputs memory problems report

2) MEMORY USAGE key [SAMPLES count] – Estimate memory usage of key

3) MEMORY STATS – Show memory usage details

4) MEMORY PURGE – Ask the allocator to release memory

5) MEMORY MALLOC-STATS – Show allocator internal stats

接下来我们从 MEMORY STATS 开始,一一介绍各个子命令的功能。

1. MEMORY STATS

首先,我们需要明确一个概念,redis 的内存使用不仅包含所有的 key-value 数据,还有描述这些 key-value 的元信息,以及许多管理功能的消耗,比如持久化、主从复制,通过 MEMORY STATS 可以更好的了解到 redis 的内存使用状况。

这里我们启动了一个打开持久化功能并且带 slave 的 redis,向其中随机写入了一些数据(某些数据还带有过期时间),以便读者可以更好的了解 redis 的内存使用,接下来执行 MEMORY STATS 命令:

127.0.0.1:6379 memory stats

 1) peak.allocated

 2) (integer) 423995952

 3) total.allocated

 4) (integer) 11130320

 5) startup.allocated

 6) (integer) 9942928

 7) replication.backlog

 8) (integer) 1048576

 9) clients.slaves

10) (integer) 16858

11) clients.normal

12) (integer) 49630

13) aof.buffer

14) (integer) 3253

15) db.0

16) 1) overhead.hashtable.main

    2) (integer) 5808

    3) overhead.hashtable.expires

    4) (integer) 104

17) overhead.total

18) (integer) 11063904

19) keys.count

20) (integer) 94

21) keys.bytes-per-key

22) (integer) 12631

23) dataset.bytes

24) (integer) 66416

25) dataset.percentage

26) 5.5934348106384277

27) peak.percentage

28) 2.6251003742218018

29) fragmentation

30) 1.1039986610412598

一共有 15 项内容,内存使用量均以字节为单位,我们一个一个来看:

1. peak.allocated

redis 启动到现在,最多使用过多少内存。

2. total.allocated

当前使用的内存总量。

3. startup.allocated

redis 启动初始化时使用的内存,有很多读者会比较奇怪,为什么我的 redis 启动以后什么都没做就已经占用了几十 MB 的内存?

这是因为 redis 本身不仅存储 key-value,还有其他的内存消耗,比如共享变量、主从复制、持久化和 db 元信息,下面各项会有详细介绍。

4. replication.backlog

主从复制 backlog 使用的内存,默认 10MB,backlog 只在主从断线重连时发挥作用,主从复制本身并不依赖此项。

5. clients.slaves

主从复制中所有 slave 的读写缓冲区,包括 output-buffer(也即输出缓冲区)使用的内存和 querybuf(也即输入缓冲区),这里简单介绍一下主从复制:

redis 把一次事件循环中,所有对数据库发生更改的内容先追加到 slave 的 output-buffer 中,在事件循环结束后统一发送给 slave。

那么主从之间就难免会有数据的延迟,如果主从之间连接断开,重连时为了保证数据的一致性就要做一次全量同步,这显然是不够高效的。backlog 就是为此而设计,master 在 backlog 中缓存一部分主从复制的增量数据,断线重连时如果 slave 的偏移量在 backlog 中,那就可以只把偏移量之后的增量数据同步给 slave 即可,避免了全量同步的开销。

6. clients.normal

除 slave 外所有其他客户端的读写缓冲区。

有时候一些客户端读取不及时,就会造成 output-buffer 积压占用内存过多的情况,可以通过配置项 client-output-buffer-limit 来限制,当超过阈值之后 redis 就会主动断开连接以释放内存,slave 亦是如此。

7. aof.buffer

此项为 aof 持久化使用的缓存和 aofrewrite 时产生的缓存之和,当然如果关闭了 appendonly 那这项就一直为 0:

redis 并不是在有写入时就立即做持久化的,而是在一次事件循环内把所有的写入数据缓存起来,待到事件循环结束后再持久化到磁盘。

aofrewrite 时缓存增量数据使用的内存,只在 aofrewrite 时才会使用,aofrewrite 机制可以参考之前的文章《redis4.0 之利用管道优化 aofrewrite》。

可以看出这一项的大小与写入流量成正比。

8. db.0

redis 每个 db 的元信息使用的内存,这里只使用了 db0,所以只打印了 db0 的内存使用状态,当使用其他 db 时也会有相应的信息。

db 的元信息有以下三项:

a) redis 的 db 就是一张 hash 表,首先就是这张 hash 表使用的内存(redis 使用链式 hash,hash 表中存放所有链表的头指针);

b) 每一个 key-value 对都有一个 dictEntry 来记录他们的关系,元信息便包含该 db 中所有 dictEntry 使用的内存;

c) redis 使用 redisObject 来描述 value 所对应的不同数据类型(string、list、hash、set、zset),那么 redisObject 占用的空间也计算在元信息中。

overhead.hashtable.main:

db 的元信息也即是以上三项之和,计算公式为:

hashtable + dictEntry + redisObject

overhead.hashtable.expires:

对于 key 的过期时间,redis 并没有把它和 value 放在一起,而是单独用一个 hashtable 来存储,但是 expires 这张 hash 表记录的是 key-expire 信息,所以不需要 `redisObject` 来描述 value,其元信息也就少了一项,计算公式为:

hashtable + dictEntry

9. overhead.total

3- 8 项之和:startup.allocated+replication.backlog+clients.slaves+clients.normal+aof.buffer+dbx

10. dataset.bytes

所有数据所使用的内存——也即 total.allocated – overhead.total——当前内存使用量减去管理类内存使用量。

11. dataset.percentage

所有数据占比,这里并没有直接使用 total.allocated 做分母,而是除去了 redis 启动初始化的内存,计算公式为:

100 * dataset.bytes / (total.allocated – startup.allocated)

12. keys.count

redis 当前存储的 key 总量

13. keys.bytes-per-key

平均每个 key 的内存大小,直觉上应该是用 dataset.bytes 除以 keys.count 即可,但是 redis 并没有这么做,而是把管理类内存也平摊到了每个 key 的内存使用中,计算公式为:

(total.allocated – startup.allocated) / keys.count

14. peak.percentage

当前使用内存与历史最高值比例

15. fragmentation

内存碎片率

2. MEMORY USAGE

相信所有 redis 用户都希望对每一个 key-value 的内存使用了如指掌,然而 4.0 之前 redis 并没有提供一个明确的方法来进行内存评估,不过从 4.0 开始,MEMORY 命令实现了这一功能。

首先看下使用方法:MEMORY usage [samples]

命令参数不多,通过字面意思也可以看出来是评估指定 key 的内存使用情况。samples 是可选参数默认为 5,以 hash 为例看下其如果工作:

首先类似于上一节中的 overhead.hashtable.main,要计算 hash 的元信息内存,包括 hash 表的大小以及所有 dictEntry 的内存占用信息。

与 overhead.hashtable.main 不同的是,每个 dictEntry 中 key-value 都是字符串,所以没 redisObject 的额外消耗。在评估真正的数据内存大小时 redis 并没有去遍历所有 key,而是采用的抽样估算:随机抽取 samples 个 key-value 对计算其平均内存占用,再乘以 key-value 对的个数即得到结果。试想一下如果要精确计算内存占用,那么就需要遍历所有的元素,当元素很多时就是使 redis 阻塞,所以请合理设置 samples 的大小。

其他数据结构的计算方式类似于 hash,此处就不再赘述。

3. MEMORY DOCTOR

此项子命令是作者给出的关于 redis 内存使用方面的建议,在不同的允许状态下会有不同的分析结果:

首先是没问题的情况

运行状态良好:

Hi Sam, I can t find any memory issue in your instance. I can only account for what occurs on this base.

redis 的数据量很小,暂无建议:

Hi Sam, this instance is empty or is using very little memory, my issues detector can t be used in these conditions. Please, leave for your mission on Earth and fill it with some data. The new Sam and I will be back to our programming as soon as I finished rebooting.

接下来出现的结果就需要注意了

内存使用峰值 1.5 倍于目前内存使用量,此时内存碎片率可能会比较高,需要注意:

Peak memory: In the past this instance used more than 150% the memory that is currently using. The allocator is normally not able to release memory after a peak, so you can expect to see a big fragmentation ratio, however this is actually harmless and is only due to the memory peak, and if the Redis instance Resident Set Size (RSS) is currently bigger than expected, the memory will be used as soon as you fill the Redis instance with more data. If the memory peak was only occasional and you want to try to reclaim memory, please try the MEMORY PURGE command, otherwise the only other option is to shutdown and restart the instance.

内存碎片率过高超过 1.4,需要注意:

High fragmentation: This instance has a memory fragmentation greater than 1.4 (this means that the Resident Set Size of the Redis process is much larger than the sum of the logical allocations Redis performed). This problem is usually due either to a large peak memory (check if there is a peak memory entry above in the report) or may result from a workload that causes the allocator to fragment memory a lot. If the problem is a large peak memory, then there is no issue. Otherwise, make sure you are using the Jemalloc allocator and not the default libc malloc.

每个 slave 缓冲区的平均内存超过 10MB,原因可能是 master 写入流量过高,也有可能是主从同步的网络带宽不足或者 slave 处理较慢:

Big slave buffers: The slave output buffers in this instance are greater than 10MB for each slave (on average). This likely means that there is some slave instance that is struggling receiving data, either because it is too slow or because of networking issues. As a result, data piles on the master output buffers. Please try to identify what slave is not receiving data correctly and why. You can use the INFO output in order to check the slaves delays and the CLIENT LIST command to check the output buffers of each slave.

普通客户端缓冲区的平均内存超过 200KB,原因可能是 pipeline 使用不当或者 Pub/Sub 客户端处理消息不及时导致:

Big client buffers: The clients output buffers in this instance are greater than 200K per client (on average). This may result from different causes, like Pub/Sub clients subscribed to channels bot not receiving data fast enough, so that data piles on the Redis instance output buffer, or clients sending commands with large replies or very large sequences of commands in the same pipeline. Please use the CLIENT LIST command in order to investigate the issue if it causes problems in your instance, or to understand better why certain clients are using a big amount of memory.

4. MEMORY MALLOC-STATS

打印内存分配器状态,只在使用 jemalloc 时有用。

5. MEMORY PURGE

请求分配器释放内存,同样只对 jemalloc 生效。

到此,关于“redis4.0 下 MEMORY 命令详解”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-28发表,共计6843字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)