怎样快速找出Redis中的BigKeys
前言
Redis中的BigKey就是key对应的value占用内存很大,在数据读取时,可能会发生阻塞,服务性能下降,甚至可能发生系统崩溃。
怎么定义为BigKey
对于不同的数据类型,定义不同:
String类型:根据数据量,value值超过10KB
List类型:根据列表大小,列表大小超过20000
Set类型:根据成员多少,成员超过10000
Hash类型:成员的数据量过大,它的成员数量虽然只有1000个但这些成员的Value总大小为100 MB
在实际业务中,您需要根据Redis的实际业务场景进行综合判断。
BigKey可能造成的问题
- 查询BigKey时用时较长,有可能会阻塞其它请求。
- Redis内存达到maxmemory参数定义的上限引发操作阻塞或重要的Key被逐出,甚至引发内存溢出(Out Of Memory)。
- 集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。
- 查询BigKey时,可能造成网络带宽占满,影响其它服务。
- 对大Key执行删除操作,易造成主库较长时间的阻塞,进而可能引发同步中断或主从切换。
怎样发现BigKey
redis-cli的参数–bigKeys
Redis提供了bigkeys参数能够使redis-cli以遍历的方式分析Redis实例中的所有Key,并返回Key的整体统计信息与每个数据类型中Top1的大Key,bigkeys仅能分析并输入六种数据类型(STRING、LIST、HASH、SET、ZSET、STREAM)
redis-cli --bigkeys
若您只需要分析STRING类型的大key或是找出成员数量超过10个的HASH Key,则bigkeys参数无法直接实现该类需求。
优点:方便、快速、安全
缺点:分析结果不可定制化,准确性与时效性差
Redis内置命令
不同的数据类型使用不同的命令,这命令风险较低,通过返回的字节数或者成员数量来判断是否是BigKey。
- String类型:执行STRLEN命令,返回对应Key的value的字节数。
- List类型:执行LLEN命令,返回对应Key的列表长度。
- Hash类型:执行HLEN命令,返回对应Key的成员数量。
- Set类型:执行SCARD命令,返回对应Key的成员数量。
- Zset类型:执行ZCARD命令,返回对应Key的成员数量。
127.0.0.1:6379> strlen mystr
(integer) 461376
127.0.0.1:6379> llen mylist
(integer) 7
127.0.0.1:6379> hlen myhash
(integer) 1
127.0.0.1:6379> scard myset
(integer) 6
127.0.0.1:6379> zcard myzset
(integer) 3
注意:
debug object与memory usage命令在执行时需占用较多资源,且时间复杂度为O(N),有阻塞Redis实例的风险,不建议使用。
127.0.0.1:6379> memory usage mystr
(integer) 524336
127.0.0.1:6379> debug object mystr
Value at:0x7f3199a305b0 refcount:1 encoding:raw serializedlength:5407 lru:1420995 lru_seconds_idle:316
优点:方便、对服务影响小
缺点:返回的Key序列化长度并不等同于它在内存空间中的真实长度,因此不够准确,仅可作为参考。(memory usage相对来说较为准确)
redis-rdb-tools
Rdbtools是Redis的dump.rdb文件的解析器,可以全面地分析Redis实例中所有Key的内存占用情况,Rdbtools是用Python编写的,使用前需要安装好Python。下面详细介绍一下安装使用
- 安装python-lzf
python-lzf是可选的,但强烈建议安装,加快解析速度。
要从PyPI安装(推荐):
pip install rdbtools python-lzf
- 安装redis-rdb-tools
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
sudo python setup.py install
- 解析RDB文件–rdb
解释一下rdb常用参数
[root@VM-16-13-centos redis-rdb-tools]# rdb --help
usage: usage: rdb [options] /path/to/dump.rdb
Example : rdb --command json -k "user.*" /var/redis/6379/dump.rdb
positional arguments:
// 从线上服务上导下来的rdb文件
dump_file RDB Dump file to process
// 可选参数
optional arguments:
// 查看rdb相关指令
-h, --help show this help message and exit
// 对rdb执行什么样的操作
// json: 以JSON格式导出数据
// diff: 分析两个rdb文件的不同
// justkeys: 只导出keys
// justkeyvals: 导出keys和values
// memory:导出内存数据(推荐使用)
// protocol: 按RESP协议导出
-c CMD, --command CMD
Command to execute. Valid commands are json, diff,
justkeys, justkeyvals, memory and protocol
// 分析出的数据以文件形式输出,通常输出Excel
-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
// 指定数据类型,默认全部
-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
// 将内存输出限制为大于或等于此值(字节)
-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)
// 字符串转义
-e {raw,print,utf8,base64}, --escape {raw,print,utf8,base64}
Escape strings to encoding: raw (default), print,
utf8, or base64.
-x, --no-expire With protocol command, remove expiry from all keys
-a N, --amend-expire N
With protocol command, add N seconds to key expiry
time
导出内存数据到Excel示例
rdb -c memory /usr/local/redis-6.2.11/dump.rdb -f memory.csv
非常直观看出key的相关信息,通过size_in_bytes轻而易举找出BigKey。
还可以指定找出10K以上的key
rdb -c memory -b 1024 /usr/local/redis-6.2.11/dump.rdb -f memory.csv
可以指定Key导出
rdb -c memory -k mylist /usr/local/redis-6.2.11/dump.rdb -f memory.csv
也可以正则匹配Key
rdb -c memory -k "mys.*" /usr/local/redis-6.2.11/dump.rdb -f memory.csv
优点:内存数据比较全,根据不同参数可定制化分析,对线上服务无影响
缺点:时效性较差,因为RDB文件不是实时更新的,还有如果RDB文件比较大的话,分析时间较慢