背景
由于公司内部,有台测试服务器,每天的内容会被莫名重置数据,怀疑是rdb文件内容有误,尝试查看rdb文件内容,顺便记录解决方案,分享给大家。
环境介绍
| 软件名称 | 版本信息 |
|---|---|
| Centos | 7.9 |
| Python | 3.9 |
| pip | 24.1.2 |
rdb分析工具使用
- 安装分析工具
bash
# 方法1:pip 安装
pip install rdbtools python-lzf
# 方法2:从源码安装
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python setup.py install
- 基本的工具使用
bash
# 生成所有数据的 JSON
rdb --command json dump.rdb > dump.json
# 只输出特定数据库
rdb -n 0 --command json dump.rdb > db0.json
# 只输出特定 key 模式
rdb --command json --key "xxx*" dump.rdb > model_keys.json
- 完整参数展示
bash
[root@VM-34-7-centos redis]# rdb --help
usage: usage: rdb [options] /path/to/dump.rdb
Example : rdb --command json -k "user.*" /var/redis/6379/dump.rdb
positional arguments:
dump_file RDB Dump file to process
optional arguments:
-h, --help show this help message and exit
-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.
-k KEYS, --key KEYS Keys to export. This can be a regular expression
-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)
-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
排查思路
排查Redis连接信息
bash
# 查看当前所有客户端连接
redis-cli CLIENT LIST
# 查看客户端地址和命令
redis-cli -a passwd CLIENT LIST | grep -E "addr=|cmd="
id=1261 addr=xxxx:27068 fd=181 name= age=6504 idle=2 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
字段详细解析
id=1261:客户端连接 ID = 1261(Redis 内部标识)
addr=xxxx:27068:客户端地址 = IP:端口(xxxx 可能是你的服务器IP)
fd=181:文件描述符 = 181(操作系统级别的标识)
name=:客户端名称(空,表示没有设置名称)
age=6504:连接已建立 6504 秒 ≈ 1小时48分钟
idle=2:空闲时间 = 2 秒(上次命令到现在的时间)
flags=N:
- N = 普通客户端(Normal)
- 其他可能值:b=阻塞, x=事务中, s=从节点, M=主节点等
db=0:当前选择的数据库编号 = 0(默认库)
sub=0:订阅的频道数 = 0(不是 Pub/Sub 订阅者)
psub=0:订阅的模式数 = 0
multi=-1:
- -1 = 不在事务中
- 如果是 1、2等 = 在事务中,队列中的命令数
qbuf=0:查询缓冲区大小 = 0 字节(当前无待处理命令)
qbuf-free=0:查询缓冲区空闲空间 = 0 字节
obl=0:输出缓冲区长度 = 0(固定缓冲区)
oll=0:输出缓冲区对象数 = 0(列表缓冲区)
omem=0:输出缓冲区内存使用 = 0 字节
events=r:
- r = 可读(ready to read)
- 其他可能:w=可写
cmd=ping:最后一次执行的命令 = PING
查看redis最近执行的命令
bash
# 查看 Redis 最近执行的命令
redis-cli MONITOR | grep -E "(SET|DEL|FLUSH|EXPIRE)" > redis_commands.log
1764729674.040258 [10 xxxx:37183] "SETNX" "ViiT:" "\"1\""
各字段含义:
1764729674.040258:Unix 时间戳(精确到微秒)
[10 xxxx:37183]:10:Redis 数据库编号(db 10)
xxxx:37183:客户端地址和端口(IP:端口)
"SETNX" "ViiT:" ""1"":执行的命令
SETNX:Set if Not eXists(仅当 key 不存在时才设置)
ViiT::键名(key)
"\"1\"":值(字符串 "1",注意有双引号)
检查客户端来源进程
bash
netstat -tunap | grep :port
tcp6 0 0 xxx:55075 xxxx:6379 ESTABLISHED 13038/java
在客户端过滤开放的客户端端口,可以看到那个进程去连接的Redis服务。
总结
通过这些排查方法,获取连接信息之后,跟开发确认是否正常,排除掉异常客户端后,重置数据的问题被解决了。