内存分析

线上经常遇到用户想知道自己 Redis 实例中数据的内存分布情况。为了不影响线上实例的使用,我们一般会采用 bgsave 生成 dump.rdb 文件,再结合 redis-rdb-tools 和 sql 来进行静态分析。总的来说,整个分析的过程简单而实用,是每一个 Redis 的用户都非常值得掌握的一个方法。

创建备份

Redis 可在客户端执行 bgsave 生成 rdb 文件

1
2
3
4
5
6
7
8
127.0.0.1:6401> bgsave
Background saving started
[root@mha-manager data]# ll /usr/local/redis-sentinel/redis1/data/
total 257808
-rw-r--r-- 1 root root 193360335 Jun 16 16:12 appendonly.aof
-rw-r--r-- 1 root root 31586138 Jun 16 18:13 dump.rdb
-rw-r--r-- 1 root root 39030784 Jun 16 18:20 memory.csv
-rw-r--r-- 1 root root 112 Jun 16 11:40 nodes-6301.conf

redis-rdb-tools

redis-rdb-tools 是一个 python 的解析 rdb 文件的工具,主要有以下三个功能:

  • 生成内存快照
  • 转储成 json 格式
  • 使用标准的 diff 工具比较两个 dump 文件

在分析内存的使后,我们主要用到它的生成内存快照功能。

安装

1
2
3
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
sudo python setup.py install

1
pip install rdbtools

生成内存快照

1
rdb -c memory dump.rdb > memory.csv

生成 CSV 格式的内存报告。包含的列有:数据库 ID,数据类型,key,内存使用量(byte),编码。内存使用量包含 key、value 和其他值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@mha-manager data]# rdb -c memory dump.rdb >memory.csv    
[root@mha-manager data]#
[root@mha-manager data]# ll
total 264476
-rw-r--r-- 1 root root 193360335 Jun 16 16:12 appendonly.aof
-rw-r--r-- 1 root root 31586138 Jun 16 18:13 dump.rdb
-rw-r--r-- 1 root root 45850811 Jun 16 18:21 memory.csv
-rw-r--r-- 1 root root 112 Jun 16 11:40 nodes-6301.conf
[root@mha-manager data]# head memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,key:000004721170,224,string,128,128
0,string,key:000002669304,224,string,128,128
0,string,key:000002009281,224,string,128,128
0,string,key:000002656076,224,string,128,128
0,string,key:000002109116,224,string,128,128
0,string,key:000003224694,224,string,128,128
0,string,key:000003397629,224,string,128,128
0,string,key:000000839412,224,string,128,128
0,string,key:000001268084,224,string,128,128

分析内存快照

将csv导入sqllite:

1
2
3
4
5
6
7
[root@mha-manager data]# sqlite3 memory.db  #在当前目录创建memory.db库
SQLite version 3.6.20
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128));
sqlite> .mode csv memory #设置memory表的输出模式
sqlite> .import memory.csv memory #导入来自 memory.csv 文件的数据到 memory 表中

接下来就可以使用sql进行分析了。

查询key个数

1
2
3
sqlite> select count(*) from memory;
1018907

查询总的内存占用

1
2
sqlite> select sum(size_in_bytes) from memory;
228234616.0

查询内存占用最高的10 key

1
2
3
4
5
6
7
8
9
10
11
sqlite> select * from memory order by size_in_bytes desc limit 10;
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,key:000004721170,224,string,128,128
0,string,key:000002669304,224,string,128,128
0,string,key:000002009281,224,string,128,128
0,string,key:000002656076,224,string,128,128
0,string,key:000002109116,224,string,128,128
0,string,key:000003224694,224,string,128,128
0,string,key:000003397629,224,string,128,128
0,string,key:000000839412,224,string,128,128
0,string,key:000001268084,224,string,128,128

查询成员个数1000****个以上的 list

1
sqlite> select * from memory where type='list' and num_elements > 1000 ;

当然也可以导入mysql分析。