通过Mysql分析Redis的内存快照数据

图片来自pixabay.com的mrgajowy3会员

本文描述了如何将Redis的内存快照数据导出,然后导入到Mysql,通过Mysql实现对Redis的内存数据分析,获取键值总数、内存消耗最大键值等信息。

1. 环境版本

本文的演示环境如下,

  • Mysql 5.7(安装在windows)
  • Python 3.6(安装在linux)
  • Redis 3.2.5(安装在linux)

2. 获取Redis内存快照

登录Redis客户端,执行bgsave命令,此命令将当前Redis的内存快照保存为dump.rdb文件

$ ./redis-3.2.5/bin/redis-cli -h localhost
localhost:6379> bgsave
Background saving started

Redis服务端将显示如下日志,

8961:M 01 Apr 21:12:06.419 * Background saving started by pid 9505
9505:C 01 Apr 21:12:06.440 * DB saved on disk
9505:C 01 Apr 21:12:06.441 * RDB: 0 MB of memory used by copy-on-write
8961:M 01 Apr 21:12:06.533 * Background saving terminated with success

生成的dump.rdb文件位于,

  • 缺省文件位置:./redis-3.2.5/bin/dump.rdb
  • 自定义文件位置:见redis.conf文件中的配置项dbfilename dump.rdb,该配置项可以改变dump.rdb文件的保存位置。

3. 通过rdb工具导出csv格式数据

3.1 安装rdb工具

工具rdb是一个Python工具,需要预先安装Python,然后执行如下命令,

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
# - 在windows系统
venv\Scripts\activate.bat
# - 在linux系统
source venv\Scripts\activate

# 安装依赖
pip install rdbtools
pip install python-lzf

注1:Windows7上安装rdbtools,会出现如下报错信息。根据提示,rdbtools需要安装Microsoft Visual C++ 14.0。

error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/

注2:安装python-lzf,这是由于在下一步解析dump文件时,该工具能够加快解析速度。不安装的话,将会有提示信息:Parsing dump file will be very slow unless you install it。

3.2 导出csv格式数据

在安装rdbtools好了后,执行如下命令,通过rdb工具解析dump文件为csv文件。

rdb -c memory dump.rdb > memory.csv

打开memory.csv文件,可以看到里面内容格式如下,

database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry
0,string,username,72,string,8,8,
0,string,test,48,string,8,8,
......

里面包括了如下的redis键值信息,

  • 数据库
  • 键类型
  • 键名
  • 占用内存空间大小
  • 编码
  • 元素个数
  • 最大元素大小
  • 失效时间

接下来就可以将memory.csv文件导入到Mysql进行下一步的统计分析。

4. 导入csv内存快照数据到Mysql

  1. 打开Mysql客户端,执行如下sql(请预先创建好数据库datareport),创建表memory,
    DROP TABLE IF EXISTS `datareport`.`memory`;
    create table IF NOT EXISTS `datareport`.`memory` (
    `database` int,
    `type` varchar(128),
    `key` varchar(128),
    `size_in_bytes` int,
    `encoding` varchar(128),
    `num_elements` int,
    `len_largest_element` int,
    `expiry` varchar(128),
    KEY `idx_type` (`type`),
    KEY `idx_key` (`key`),
    KEY `idx_size_in_bytes` (`size_in_bytes`),
    KEY `idx_num_elements` (`num_elements`),
    KEY `idx_len_largest_element` (`len_largest_element`)
    );
    
  2. 复制文件memory.csv到C:/ProgramData/MySQL/MySQL Server 5.7/Uploads目录下。
    • 打开复制的memory.csv文件,删除如下第一行表头数据。
    database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry
    
  3. 执行如下sql命令,加载csv数据到表
    LOAD DATA INFILE'C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/memory.csv' replace INTO TABLE `datareport`.`memory` FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '"' LINES TERMINATED BY '\n';
    

    根据数据文件大小和机器配置,该加载过程时间会比较长,150MB的memory.csv文件耗时可能达1个小时。

5. 通过Mysql分析Redis内存数据

数据导入到数据库后,接下来就可以进行一些数据统计分析了,下面给出几个数据统计样例。

  1. 查询key个数
    SELECT COUNT(*) FROM `memory`;
    
  2. 查询总的内存占用
    SELECT SUM(size_in_bytes) FROM `memory`;
    
  3. 查询内存占用最高的前10个key
    SELECT * FROM `memory` ORDER BY size_in_bytes DESC LIMIT 10;
    
  4. 查询成员个数1000个以上的list/hash
    SELECT * FROM `memory` WHERE TYPE='quicklist' AND num_elements > 1000;
    
  5. 查询成员个数最多的前100个hash/set/sortedset
    SELECT * FROM MEMORY WHERE TYPE='hash' ORDER BY num_elements DESC LIMIT 100;
    SELECT * FROM MEMORY WHERE TYPE='set' ORDER BY num_elements DESC LIMIT 100;
    SELECT * FROM MEMORY WHERE TYPE='sortedset' ORDER BY num_elements DESC LIMIT 100;
    
  6. 保存数据到文件中
    SELECT * FROM `memory` ORDER BY size_in_bytes DESC LIMIT 10 INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/total.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '"' LINES TERMINATED BY '\r\n';
    

6. 参考资料

  1. 阿里云:Redis 内存分析方法