背景
Redis是基于内存的KV数据库,内存作为存储介质,关注其内存的使用情况是一个重要指标,解析其内部的存储信息是给出优化方法和维护的最基本要求。解析内存有二种方法:第一个是通过scan遍历所有key,针对每个key进行分析(memory usage);第二个是基于RDB文件进行所有key的分析(redis-rdb-tools)。本文将介绍如何使用rdbtools工具。
说明
rdbtools工具包括了3个可执行文件:
rdb -- 解析整个rdb文件 redis-memory-for-key -- 解析server里的单个key redis-profiler --解析rdb文件成html格式
rdb是rdbtools工具包其中之一的工具,也是解析dump.rdb文件的工具:分析内存并将数据导出到JSON,Rdbtools是Redis的dump.rdb文件的解析器,解析器生成类似于xml。rdbtools提供了以下实用程序:
- 生成所有数据库和键中数据的内存报告
- 将转储文件转换为JSON
- 使用标准差异工具比较两个转储文件
安装 rdbtools
前提条件:
- 安装 python-lzf :加快解析速度
pip install python-lzf
- 安装redis-py:可选,仅在运行测试用例时需要
PyPI安装(推荐)
pip install rdbtools python-lzf
源码安装
git clone https://github.com/sripathikrishnan/redis-rdb-tools cd redis-rdb-tools sudo python setup.py install
命令行用法示例
help:
1,rdb --help:解析整个rdb文件
usage: rdb [options] /path/to/dump.rdb Example : rdb --command json -k "user.*" /var/redis/6379/dump.rdb positional arguments: -- 要处理的dump文件 dump_file RDB Dump file to process optional arguments: -- 帮助 -h, --help show this help message and exit -- 要处理的命令,-c后的有效参数为:json, diff,justkeys, justkeyvals, memory,protocol -c CMD, --command CMD Command to execute. Valid commands are json, diff, justkeys, justkeyvals, memory and protocol -- 输出文件 -f FILE, --file FILE Output file -- 数据库号,可以提供多个数据库。如果未指定,则包括所有数据库。 -n DBS, --db DBS Database Number. Multiple databases can be provided. If not specified, all databases will be included. -- 要导出的key。这可以是一个正则表达式 -k KEYS, --key KEYS Keys to export. This can be a regular expression -- key不导出。这可以是一个正则表达式 -o NOT_KEYS, --not-key NOT_KEYS Keys Not to export. This can be a regular expression -- 解析的数据类型。可能的值为string,hash,set,sortedset,list。可以输入多种类型提供。如果未指定,则为所有数据类型 -t TYPES, --type TYPES Data types to include. Possible values are string, hash, set, sortedset, list. Multiple typees can be provided. If not specified, all data types will be returned -- 将key的内存输出限制为大于或等此值(以字节为单位) -b BYTES, --bytes BYTES Limit memory output to keys greater to or equal to this value (in bytes) -- 将内存按大小输出前N个key -l LARGEST, --largest LARGEST Limit memory output to only the top N keys (by size) -- 将字符串转义为编码:raw(默认),print,utf8或base64。 -e {raw,print,utf8,base64}, --escape {raw,print,utf8,base64} Escape strings to encoding: raw (default), print, utf8, or base64. -- 使用command protocol参数,从所有键中删除到期的key -x, --no-expire With protocol command, remove expiry from all keys -- 使用command protocol参数,将N秒添加到key的到期时间 -a N, --amend-expire N With protocol command, add N seconds to key expiry time
2,redis-memory-for-key --help:-- 解析server里指定的单个key
Usage: redis-memory-for-key [options] redis-key Examples : redis-memory-for-key user:13423 redis-memory-for-key -s localhost -p 6379 user:13423 Options: -- 帮助 -h, --help show this help message and exit -- 服务地址,默认127.0.0.1 -s HOST, --server=HOST Redis Server hostname. Defaults to 127.0.0.1 -- 服务端口,默认6379 -p PORT, --port=PORT Redis Server port. Defaults to 6379 --服务密码 -a PASSWORD, --password=PASSWORD Password to use when connecting to the server -- 数据库号,默认0 -d DB, --db=DB Database number, defaults to 0
3,redis-profiler --help:
Usage: redis-profiler [options] /path/to/dump.rdb Example 1 : redis-profiler -k "user.*" -k "friends.*" -f memoryreport.html /var/redis/6379/dump.rdb Example 2 : redis-profiler /var/redis/6379/dump.rdb Options: -- 帮助 -h, --help show this help message and exit -- 输出 -f FILE, --file=FILE Output file -- 组合在一起的键。 多个正则表达式 -k KEYS, --key=KEYS Keys that should be grouped together. Multiple regexes can be provided
每次运行以上工具时都需要指定一个命令,以指示对解析的RDB数据应执行的操作。 操作有:
转储的JSON:
> rdb --command json /var/redis/6379/dump.rdb [{ "user003":{"fname":"Ron","sname":"Bumquist"}, "lizards":["Bush anole","Jackson's chameleon","Komodo dragon","Ground agama","Bearded dragon"], "user001":{"fname":"Raoul","sname":"Duke"}, "user002":{"fname":"Gonzo","sname":"Dr"}, "user_list":["user003","user002","user001"]},{ "baloon":{"helium":"birthdays","medical":"angioplasty","weather":"meteorology"}, "armadillo":["chacoan naked-tailed","giant","Andean hairy","nine-banded","pink fairy"], "aroma":{"pungent":"vinegar","putrid":"rotten eggs","floral":"roses"}}]
过滤解析:
正则表达式匹配key,并且仅打印键和值:
> rdb --command justkeyvals --key "user.*" /var/redis/6379/dump.rdb user003 fname Ron,sname Bumquist, user001 fname Raoul,sname Duke, user002 fname Gonzo,sname Dr, user_list user003,user002,user001
仅处理数据库2中hash类型的a开头的key:
> rdb -c json --db 2 --type hash --key "a.*" /var/redis/6379/dump.rdb [{},{ "aroma":{"pungent":"vinegar","putrid":"rotten eggs","floral":"roses"}}]
dump文件转换为JSON:
输出是UTF-8编码的JSON。 默认情况下,回调尝试使用UTF-8解析RDB数据,并使用U表示符转义非'ASCII可打印'字符,或使用x转义非UTF-8可解析的字节。 尝试对RDB数据进行解码可能会导致二进制数据错误,可以通过使用--escape raw选项来避免这种情况。 另一种选择是使用-e base64进行二进制数据的Base64编码。
解析dump文件并在标准输出上打印JSON:
> rdb -c json /var/redis/6379/dump.rdb [{ "Citat":["Bu00e4ttre sent u00e4n aldrig","Bra karl reder sig sju00e4lv","Man ska inte ku00f6pa grisen i su00e4cken"], "bin_data":"\xFEu0000u00e2\xF2"}]
将dump文件解析为原始字节,并在标准输出上打印JSON:
> rdb -c json /var/redis/6379/dump.rdb --escape raw [{ "Citat":["Bu00c3u00a4ttre sent u00c3u00a4n aldrig","Bra karl reder sig sju00c3u00a4lv","Man ska inte ku00c3u00b6pa grisen i su00c3u00a4cken"], "bin_data":"u00feu0000u00c3u00a2u00f2"}]
生成内存报告:
使用-c memory 运行会生成CSV报告,其中包含该键使用的近似内存。 --bytes C 和 --largest N 可用于将输出限制为大于C字节的键或N个最大键。
> rdb -c memory /var/redis/6379/dump.rdb --bytes 128 -f memory.csv > cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 0,list,user_list,190,quicklist,3,7 2,hash,baloon,138,ziplist,3,11 2,list,armadillo,231,quicklist,5,20 2,hash,aroma,129,ziplist,3,11
生成的CSV具有以下列:
database:数据库编号 type:数据类型 key:键 size_in_bytes:使用的内存:包括键,值和任何其他开销 encoding:RDB编码类型 num_elements:key中的value的个数 len_largest_element:key中的value的长度 expiry:过期值
注意:内存使用情况是近似的。 通常,实际使用的内存将略高于报告的内存。可以按键或数据库编号或数据类型过滤报告。内存报告应有助于检测由应用程序逻辑引起的内存泄漏。 它还将帮助优化Redis的内存使用。
查找单键使用的内存:
查找特定键使用的内存(运行整个内存报告非常耗时),使用redis-memory-for-key:
> redis-memory-for-key person:1 > redis-memory-for-key -s localhost -p 6379 -a mypassword person:1 Key person:1 Bytes 111 Type hash Encoding ziplist Number of Elements 2 Length of Largest Element 8
比较RDB文件:
使用--command diff选项,并将输出通过管道传递到标准sort:
> rdb --command diff /var/redis/6379/dump1.rdb | sort > dump1.txt > rdb --command diff /var/redis/6379/dump2.rdb | sort > dump2.txt
运行差异程序:
> kdiff3 dump1.txt dump2.txt
要限制文件的大小,可以使用--key选项过滤键
使用Redis协议:
使用protocol命令将RDB文件转换为redis协议流:
> rdb -c protocol /var/redis/6379/dump.rdb *4 $4 HSET $9 users:123 $9 firstname $8 Sripathi
可以将输出通过管道传输到netcat并重新导入数据的子集。如果要将数据在两个Redis实例上共享,则可以使用--key标志选择数据的子集,然后将输出传递给正在运行的Redis实例并加载该数据。 当输出打印协议时,--escape选项可以避免出现不可打印/控制字符。
默认情况下,如果过期时间在rdb文件中存在,则会删除过去所有过期的键。 如果不需要此行为,则使用-x/--no-expire选项将忽略所有关键的到期命令。使用-a/--amend-expire选项设置将来的到期时间,该选项会为已设置为到期的每个密钥的到期时间增加整数秒,不会更改尚未设置有效期的key。
使用解析器(Python):

测试说明
一、rdb:根据要求分析这个RDB文件
- 按json格式导出rdb:rdb --command json dump.rdb
View Code
-
导出rdb中的keys:rdb -c justkeys dump.rdb
View Code
- 导出rdb中的values:rdb -c justkeyvals dump.rdb
View Code
- 导出rdb中keys的内存分析:rdb -c memory dump.rdb
View Code
- 按RESP协议导出RDB内容:rdb -c protocol dump.rdb
View Code
- 分析RDB结果导出到文件:rdb -c memory dump.rdb -f ttt.csv
View Code
- 导出指定数据库的keys:rdb -c justkeyvals dump.rdb -n 0
View Code
- 导出匹配(正则)的keys:rdb --command justkeyvals --key ".*set*" dump.rdb
View Code
- 不导出匹配(正则)的keys:rdb --command justkeyvals --not-key ".*set*" dump.rdb
View Code
- 导出指定类型的keys:rdb --command json --type hash dump.rdb
View Code
- 导出大于指定字节的keys:rdb --command memory --bytes 128 dump.rdb
View Code
- 导出内存字节排名前3个keys:rdb --command memory --largest 3 dump.rdb
View Code
- 导出指定编码转义:rdb --command justkeyvals --escape raw dump.rdb
View Code
- 导出keys(过期keys除外):rdb --command memory --no-expire dump.rdb
- 导出keys(给过期keys添加时间):rdb --command memory --amend-expire 100 dump.rdb
以上操作参数可以相互叠加使用,按照实际要求进行组合。并且可以导出成csv文件,导入到数据库里进行聚合统计和监控。
二、redis-memory-for-key:查看指定key的内存
查看指定key的内存分析情况:redis-memory-for-key --server=192.168.163.134 --port=8379 f

三、redis-profiler:RDB分析生成html

分析后的效果图(一部分)如:
总结
通过本文对于rdbtools说明,能够更好的解析RDB其内部的存储信息,从而方便给出优化和维护的建议,关于rdbtools更多的说明可以看官网。