Redis 实用小技巧—— key 分布情况分析

背景

在实际生产中,随着业务体系越来越庞大,Redis 的使用量也会随之上升,当 Redis 数据库变的越来越大时,我们经常会遇到以下几种问题:

  1. key 的数据类型分布问题:类型使用是否合理?
  2. key 的存储空间占用问题:是否存在一定数量的 bigkey ?
  3. key 的过期时间问题:是否存在大量未设置过期的 key ?key 是否存在集中过期的情况?

从上述问题不难看出,此类场景下我们并非关注的是具体的某个 key ,而是 key 的一个整体分布的情况。下面我们就针对这些问题来看看具体应该如何解决。

方案

rdbtools 是一款 Redis rdb 分析工具,可以通过 rdb 文件生成内存报告。因此,我们可以考虑借助这个工具来解决上述场景出现的问题。

步骤一:安装 python3

rdbtools 依赖 python3 版本,如果系统有预装的 python2 版本,可使用以下方法先进行卸载,然后再重新安装。

1. 强制卸载旧版本的 python (以 Linux 为例):
rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps
whereis python |xargs rm -frv
whereis python
2. 下载源码压缩包
wget https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tgz
3. 编译准备工作
mkdir -p /usr/local/python3
tar -zxvf Python-3.9.9.tgz 
cd Python-3.9.9.tgz
./configure --prefix=/usr/local/python3 
4. 编译安装
$ make && make install
5. 设置软连接
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
ln -s /usr/local/python3/bin/python3 /usr/bin/python
6. 配置环境变量

首先打开环境变量配置文件:

vim /etc/profile

新增以下配置:

export PATH=$PATH:/usr/local/python3/bin

然后重新加载环境变量。

source /etc/profile

到这里 python3 就已经安装好了,命令行输入:

python --version
pip --version

如果可以看到版本信息的话,说明 python3 和 pip3 已经安装成功。

步骤二:安装 rdbtool

1. 升级 pip 版本

如果提示 pip 版本过低问题,可按照下面命令进行升级:

/usr/bin/python3 -m pip install --upgrade pip
2. 升级 setuptools 版本

如果提示 setuptools 版本过低问题,可按照下面命令进行升级:

pip3 install --upgrade setuptools
3. 安装rdbtools
pip install rdbtools python-lzf

安装完成以后,命令行下输入以下命令,如果出现帮助提示,证明安装成功。

rdb --help

步骤三:生成 rdb 文件

这里我们分别介绍如何从本地和云端生成 rdb 文件。

本地服务器生成 rdb 文件

1. 修改 Redis 配置文件

通过以下命令查看 Redis 配置文件位置:

redis-cli info server | grep config_file

修改 rdb 文件的名称和存储位置(存储位置可自定义,具有操作权限即可)。

vim /usr/local/redis/etc/redis.conf

指定 rdb 文件的名称和路径。

dbfilename 6379.rdb
dir /usr/local/redis/data/

修改完配置以后,需要重启 Redis 服务器。

2. 动态修改 Redis 配置

动态修改 Redis 配置是在不重启 Redis 服务的情况下直接生效(重启 Redis 服务会导致服务短暂不可用或数据丢失)

redis-cli CONFIG SET "dbfilename" "6379.rdb"
redis-cli CONFIG SET "dir" "/usr/local/redis/data/"

1 和 2 步骤选择一种执行即可,不必重复执行。

3. 生成 rdb 文件
redis-cli BGSAVE

执行完命令后会在配置的路径下生成二进制的 rdb 文件。

阿里云 Redis 服务获取 rdb 文件

阿里云 Redis 在以下位置进行下载即可。

阿里云 Redis 服务获取 rdb 文件

步骤四:分析数据

分析数据之前我们先来了解一下 rdb 命令的用法。

rdb [options] /path/to/dump.rdb

例如: rdb --command json -k "user.*" /var/redis/6379/dump.rdb

其中 rdb 文件路径为必传参数,其他可选的参数如下所示:

短参数 长参数 描述
-h –help 显示帮助信息
-c CMD –command CMD 可执行的命令。有效的命令包括:jsondiffjustkeysjustkeyvalsmemoryprotocol
-f FILE –file FILE 输出文件
-n DBS –db DBS 数据库编号。可以提供多个数据库编号,如果缺省将处理所有数据库的数据
-k KEYS –key KEYS 导出的键。可以是正则表达式
-o NOT_KEYS –not-key NOT_KEYS 不导出的键。可以是正则表达式
-t TYPES –type TYPES 导出键的类型。支持的类型有:stringhashsetsortedsetlist。支持提供多个类型导出,缺省则导出所有类型
-b BYTES –bytes BYTES 仅输出大于或等于指定值的键
-l LARGEST –largest LARGEST 仅输出内存排名前N的键
-e {raw,print,utf8,base64} –escape {raw,print,utf8,base64} 字符串编码格式
-x –no-expire 通过协议命令排除过期的键
-a N –amend-expire N 通过协议命令给键增加N秒的过期时间

了解了 rdb 的基本使用,就可以借助它生成分析文件了。接下来介绍如何生成分析文件和常见问题的处理。

生成分析文件命令如下(这里以 memory 命令为例,生成 csv 格式的分析文件):

rdb -c memory -f 6379.csv /usr/local/redis/data/6379.rdb

查看生成的分析报告:

cat 6379.csv

文件内容如下:

  database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry 
  0,hash,foo-4,83,ziplist,3,2,
  0,sortedset,foo-6,83,ziplist,4,2,
  0,list,foo-7,163,quicklist,6,2,
  0,set,foo-5,396,hashtable,5,2, 
  0,string,foo-1,56,string,5,5,
  0,string,foo-2,56,string,5,5, 
  0,string,foo-3,88,string,5,5,2022-07-02T12:46:09.122000

可以看到,用工具转化成 csv 文件后,会划分成 8 个列,分别是:

列名称 含义
database 数据库编号
type 数据类型
key
size_in_bytes 使用的内存:包括键、值和其他任何开销
encoding RDB 编码类型
num_elements 键中元素的个数
len_largest_element 最大元素的长度
expiry 过期时间

有了这些信息,下一步就是如何借助这些信息来解决我们开头提到的那些问题了。可以通过 rdb 自带的参数实现,也可以借助外部的工具或者命令实现。

问题一:查询所有未设置过期的键
rdb -c justkeys -x /usr/local/redis/data/6379.rdb
问题二:查询各数据类型的键的分布

统计数据库中字符串类型的键的个数

rdb -c justkeys -t string /usr/local/redis/data/6379.rdb | wc -l
问题三:查询占内存最大的前 N 个键
rdb -c memory -l {N} /usr/local/redis/data/6379.rdb

说明:
使用 redis-cli --bigkeys 也可以统计 Redis 的大 key ,但是该命令只能统计每种数据类型下占内存最大的 key ,如果需要找出限制大小条件的大 key ,使用此命令就不合适了。但是此命令还具有生成内存分析报告( summary )的功能,可以生成键内存使用情况的分析报告,在一些情况下也可以帮助分析 Redis 的内存占用情况。

问题四:查询某个前缀的所有的键
rdb -c justkeys -k "{keyname}" /usr/local/redis/data/6379.rdb

在生产环境需要批量对特定的键进行操作时,如果仅知道键的前缀的话,可以采用此种方法先获取到所有符合条件的键,然后再通过脚本进行处理,能够大大提高处理效率。

问题五:查看某个键占用内存的大小
$ rdb -c memory -k "{keyname}" /usr/local/redis/data/6379.rdb

也可以通过 redis-memory-for-key(安装 rdbtools 工具时会默认安装这个工具)这个工具直接查看键的占用内存的大小,更加快捷方便,使用该命令无须生成 rdb 文件,可以直接连接redis服务器进行查看。具体用法如下:

redis-memory-for-key {keyname}

输出结果如下:

  Key           keyname
  Bytes             56
  Type          string

更多 redis-memory-for-key 用法如下:

短参数 长参数 描述
-h –help 显示帮助信息
-s HOST –server=HOST Redis 服务器地址
-p PORT –port=PORT Redis 服务器端口号
-a PASSWORD –password PASSWORD Redis 服务器密码
-d DB –db DB 数据库编号

上面介绍的是直接使用 rdb 命令进行的分析,也可以先生成报告文件,然后作为原始数据导入数据库,做一些可视化的处理工作。

总结

通过 rdbtools 工具可以对 rdb 文件进行解析并生成分析报告,报告中包含了:key 名称、类型、大小等关键信息,通过这些数据进行不同维度的分析,可以解决各种 key 分布的问题。

本作品采用《CC 协议》,转载必须注明作者和本文链接
你应该了解真相,真相会让你自由。
本帖由系统于 9个月前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 8

简单易懂,收藏了

11个月前 评论

写的非常好。 :+1:

11个月前 评论

:+1: :+1: :+1: :+1: :+1:

11个月前 评论

学习了 :+1:

11个月前 评论

很棒,学习了。

11个月前 评论

讲的很好,很有帮助

10个月前 评论

有时间研究一下

10个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!