简介:这是一份面向Redis初学者与运维开发人员的Windows端可视化数据库管理工具,以Redis Desktop Manager为核心,帮助用户摆脱命令行束缚,通过图形界面完成连接、浏览与数据操作。压缩包共630个文件,以59个dll动态库、23个exe可执行程序、20个jar包及22个properties配置为主,另含大量时区数据、字体与图片资源,整体约34.64MB,解压后运行RedisClient即可使用。工具支持连接本地或远程服务器,直观查看db0至db15中的键值对及过期时间,覆盖字符串、哈希、列表、集合、有序集合等类型的增删改查,并内置命令执行、JSON/CSV/XML导入导出、SSL与超时设置、多语言界面等功能。目前已有484人学习下载,适合需要高效管理Redis、进行数据迁移备份或性能测试的开发者参考使用。
1. 为什么我又把 Redis 可视化工具翻出来重装了一遍
上周排查一个线上缓存击穿问题,redis-cli敲了半小时SCAN、TTL、MEMORY USAGE,眼睛都快看花了。当时就想,要是有个能直接看 key 分布、能按前缀过滤、能实时刷新的可视化界面,至少能省一半时间。Redis 可视化工具就是干这个的——把 Redis 里那些二进制安全的 key、嵌套的 hash、动辄几十万元素的 zset,用图形界面摊开给你看。它适合三类人:日常要巡检缓存的后端开发、需要快速定位热 key 的运维、以及刚接触 Redis 数据结构想直观理解的学生。但这类工具坑也不少,选错了要么连不上集群,要么一开监控就把生产库拖慢。这篇就把我实际拆过、配过、踩过坑的流程完整写一遍,从选型到连集群到排错,你照着能复现。
2. 选型先看协议兼容:单机、哨兵、集群三种连法差别在哪
2.1 先搞清楚工具底层走的是什么协议
绝大多数 Redis 可视化工具底层都是封装了RESP协议,也就是 Redis 客户端和服务器之间那套文本协议。你界面上点一个 key,工具实际发出去的是TYPE key、OBJECT ENCODING key、MEMORY USAGE key这几条命令。理解这一点很重要,因为后面连不上、显示不全、刷新卡顿,根子往往不在界面,而在协议层。
常见工具有几类实现路线。一类是纯客户端直连,工具进程直接和 Redis 建 TCP 连接,比如 RedisInsight、Another Redis Desktop Manager 这类桌面端。另一类是 Web 端,中间加一层服务端代理,浏览器连代理、代理连 Redis,比如一些开源的 Web 管理面板。还有一类是命令行增强型,本质还是 CLI,只是加了 TUI 界面。
选型时我一般看三个硬指标:支不支持集群模式、支不支持 TLS、支不支持SCAN游标分批。前两个决定你能不能连上生产,第三个决定你打开一个百万 key 的库时会不会直接卡死。很多工具默认用KEYS *拉全量,这在生产库上就是灾难,一定要确认它用的是SCAN。
2.2 单机、哨兵、集群的连接参数怎么填
单机最简单,填 host、port、密码就行。哨兵模式要额外填哨兵节点列表和 master 名称,工具会先连哨兵问出当前 master 地址再连。集群模式最容易被坑,因为集群有 16384 个槽,key 分散在多个节点上,工具必须支持CLUSTER SLOTS或CLUSTER SHARDS来发现拓扑。
下面是一个典型的连接配置结构,我用伪配置的方式写出来,你对照自己工具的填写项:
# 单机 host: 127.0.0.1 port: 6379 password: your_password db: 0 # 哨兵 sentinels: - 127.0.0.1:26379 - 127.0.0.1:26380 master_name: mymaster password: your_password # 集群 cluster_nodes: - 127.0.0.1:7000 - 127.0.0.1:7001 - 127.0.0.1:7002 password: your_password # 注意:集群模式没有 db 概念,只能连 db 0逻辑说明:哨兵模式下,工具不会直接连你填的哨兵节点做数据操作,而是先发SENTINEL get-master-addr-by-name拿到 master 真实地址。集群模式下,工具连上任意一个节点后发CLUSTER SLOTS,拿到槽位和节点的映射表,之后每个 key 先算 CRC16 再对 16384 取模,路由到对应节点。
参数上最容易错的是集群的密码。有些工具把密码填在「节点密码」一栏,有些要求填在「集群密码」一栏,填错位置就连不上。另外集群模式下SELECT命令是被禁用的,如果你工具界面上还有 db 选择框,说明它没做集群适配,趁早换。
2.3 一个能跑的连接验证脚本
在把工具连上生产之前,我习惯先用脚本确认网络和权限没问题,避免在界面上瞎试。下面这段用 Python 的 redis 库做连通性验证:
import redis from redis.cluster import RedisCluster # 单机验证 def check_standalone(host, port, password): r = redis.Redis(host=host, port=port, password=password, socket_timeout=3, socket_connect_timeout=3) # ping 确认连通 print("ping:", r.ping()) # 确认能否执行 scan,而不是 keys cursor, keys = r.scan(count=10) print("scan sample:", keys[:5]) # 看下内存信息 print("used_memory_human:", r.info("memory")["used_memory_human"]) # 集群验证 def check_cluster(nodes, password): rc = RedisCluster(startup_nodes=nodes, password=password, socket_timeout=3) print("cluster ping:", rc.ping()) # 集群下 scan 要指定目标节点,这里只做连通性演示 print("cluster info:", rc.cluster_info()["cluster_state"]) if __name__ == "__main__": check_standalone("127.0.0.1", 6379, "your_password") # check_cluster([{"host": "127.0.0.1", "port": "7000"}], "your_password")逻辑说明:socket_timeout和socket_connect_timeout一定要设,默认不设的话网络不通时脚本会挂很久。scan的count参数是提示值,不是精确值,Redis 可能一次返回多于或少于 count 的 key,这是正常的。集群验证里cluster_state返回ok才说明集群健康。
参数说明:count=10适合验证,生产巡检可以调到 1000 左右,太大单次阻塞时间长,太小往返次数多。socket_timeout=3是秒,内网可以设 2,跨机房设 5。
3. 把 key 看明白:数据结构展示、内存分析和慢查询定位
3.1 五种基础类型在界面上到底怎么呈现
Redis 有 string、list、hash、set、zset 五种基础类型,加上后来的 stream、bitmap、hyperloglog、geo。可视化工具的价值就在于把这些类型用合适的控件展示出来。string 直接显示文本或十六进制,list 显示成有序列表,hash 显示成键值表格,set 显示成无序集合,zset 显示成带 score 的排序表。
这里有个坑:string 类型如果存的是序列化后的对象,比如 Java 的JdkSerializationRedisSerializer或者 Protobuf,界面上直接显示就是乱码。好的工具会提供 hex 视图和多种编码切换。我一般会先在工具里看OBJECT ENCODING key的结果,如果是embstr或raw,说明是普通字符串;如果是int,说明存的是整数;如果是listpack或quicklist,那是 list 的底层编码。
下面这段脚本可以批量看一个前缀下所有 key 的类型和编码,配合工具界面用:
import redis r = redis.Redis(host="127.0.0.1", port=6379, password="your_password") def inspect_keys(pattern, limit=50): cursor = 0 count = 0 while True: cursor, keys = r.scan(cursor=cursor, match=pattern, count=100) for k in keys: ktype = r.type(k).decode() encoding = r.object("encoding", k).decode() ttl = r.ttl(k) # memory usage 在 4.0+ 可用 try: mem = r.memory_usage(k) except Exception: mem = -1 print(f"{k.decode():40s} type={ktype:8s} enc={encoding:12s} ttl={ttl:6d} mem={mem}") count += 1 if count >= limit: return if cursor == 0: return inspect_keys("user:*")逻辑说明:scan用游标迭代,不会阻塞 Redis。type返回 key 的类型,object encoding返回底层编码,ttl返回剩余过期时间(-1 表示永不过期,-2 表示 key 不存在),memory_usage返回该 key 占用的字节数。
参数说明:match支持 glob 通配符,user:*匹配所有 user 开头的 key。count=100是每次迭代的提示数量。limit=50是脚本自己限制的输出条数,避免刷屏。
3.2 内存分析:怎么找出那些偷偷吃内存的大 key
大 key 是 Redis 最常见的性能杀手。一个几百万元素的 hash 或者 list,单次操作就可能阻塞主线程几百毫秒。可视化工具一般都有内存排序功能,但你要知道它底层调的是什么。MEMORY USAGE key是精确计算单个 key 的内存,但它是 O(N) 的,对超大 key 会慢。DEBUG OBJECT key能看序列化长度,但生产环境通常禁用了DEBUG命令。
我一般用两段式排查:先用SCAN采样,对每个 key 调MEMORY USAGE,按大小排序;再对 top N 的 key 用TYPE和STRLEN、LLEN、HLEN、SCARD、ZCARD看元素数量。
import redis import heapq r = redis.Redis(host="127.0.0.1", port=6379, password="your_password") def find_big_keys(pattern="*", sample=1000, topn=20): cursor = 0 seen = 0 heap = [] # 小顶堆,存 (mem, key) while seen < sample: cursor, keys = r.scan(cursor=cursor, match=pattern, count=100) for k in keys: try: mem = r.memory_usage(k) or 0 except Exception: mem = 0 if len(heap) < topn: heapq.heappush(heap, (mem, k)) elif mem > heap[0][0]: heapq.heapreplace(heap, (mem, k)) seen += 1 if cursor == 0: break # 从大到小输出 for mem, k in sorted(heap, reverse=True): ktype = r.type(k).decode() size = 0 if ktype == "string": size = r.strlen(k) elif ktype == "list": size = r.llen(k) elif ktype == "hash": size = r.hlen(k) elif ktype == "set": size = r.scard(k) elif ktype == "zset": size = r.zcard(k) print(f"{k.decode():50s} mem={mem:10d} type={ktype:8s} elements={size}") find_big_keys("user:*", sample=2000, topn=10)逻辑说明:用小顶堆维护 top N,避免把所有 key 都存内存里。memory_usage返回字节数,strlen、llen等返回元素个数。两者结合能判断是「元素多」还是「单元素大」。
参数说明:sample=2000是采样上限,生产库 key 多的时候不要全量扫。topn=10输出前 10 个大 key。count=100控制每次 SCAN 的批量。
3.3 慢查询和实时命令监控怎么配合工具用
可视化工具一般有「慢查询」面板和「命令监控」面板。慢查询读的是 Redis 的SLOWLOG,需要 Redis 配置了slowlog-log-slower-than阈值,默认是 10000 微秒也就是 10 毫秒。命令监控用的是MONITOR命令,会把所有执行的命令实时推给你。
这里有个血泪经验:MONITOR在生产环境慎用。它会显著增加 Redis 的 CPU 和网络开销,因为每条命令都要复制一份发给监控客户端。我一般只在排查特定问题时短时间开,比如 30 秒,抓完就关。工具界面上如果有「实时监控」开关,用完一定记得关掉。
慢查询的配置可以动态改:
# 设置慢查询阈值为 5 毫秒 redis-cli config set slowlog-log-slower-than 5000 # 慢查询日志最多保留 128 条 redis-cli config set slowlog-max-len 128 # 查看慢查询 redis-cli slowlog get 10逻辑说明:slowlog-log-slower-than单位是微秒,设成负数会关闭慢查询,设成 0 会记录所有命令。slowlog-max-len控制日志条数,太大会占内存。slowlog get后面跟条数。
参数说明:生产环境阈值一般设 5000 到 10000 微秒,也就是 5 到 10 毫秒。低于这个值的命令通常不值得关注。slowlog-max-len设 128 到 256 够用。
4. 避坑排查:连不上、显示乱码、刷新卡死的真实原因
4.1 现象:工具显示连接成功,但 key 列表是空的
原因:最常见的是连到了错误的 db。单机模式下 Redis 有 16 个 db,默认连 db 0,但你的数据可能在 db 1 或 db 2。集群模式下没有 db 概念,如果工具还让你选 db,说明它没适配集群,实际连的还是某个单机节点。
解决:先用redis-cli info keyspace看各个 db 的 key 数量,确认数据在哪个 db。集群模式下确认工具版本支持CLUSTER SLOTS,并且连接时不要指定 db。
redis-cli -h 127.0.0.1 -p 6379 -a your_password info keyspace # 输出示例: # db0:keys=1000,expires=100,avg_ttl=3600000 # db1:keys=5000,expires=0,avg_ttl=04.2 现象:key 显示出来了,但 value 是乱码
原因:value 被序列化了。Java 项目常用 JDK 序列化或 Protobuf,Python 项目可能用了 pickle,这些序列化后的字节流在界面上直接按 UTF-8 解码就是乱码。
解决:确认工具支持 hex 视图或自定义解码器。如果工具不支持,就先用脚本反序列化看内容。JDK 序列化的数据可以用redis-cli --raw get key拿到原始字节,再用对应语言的库反序列化。
import redis import pickle r = redis.Redis(host="127.0.0.1", port=6379, password="your_password") raw = r.get("user:1001:profile") # 如果是 pickle 序列化 try: obj = pickle.loads(raw) print(obj) except Exception as e: print("not pickle, raw hex:", raw.hex()[:100])逻辑说明:get返回的是 bytes,pickle.loads尝试反序列化。失败就打印 hex 前 100 字节,人工判断序列化格式。
参数说明:raw.hex()把字节转成十六进制字符串,方便看魔数。JDK 序列化的魔数是ACED,Protobuf 没有固定魔数但通常有字段编号。
4.3 现象:打开工具后 Redis 响应变慢,甚至超时
原因:工具在后台跑了KEYS *或者高频INFO。KEYS *是 O(N) 的,百万 key 的库上执行会阻塞主线程好几秒。有些工具为了显示 key 总数,每隔几秒发一次DBSIZE,虽然DBSIZE是 O(1),但高频调用也有开销。
解决:抓包或者用MONITOR短时间看工具发了什么命令。如果是KEYS *,在工具设置里找「使用 SCAN」选项,找不到就换工具。如果是高频INFO,把刷新间隔从 1 秒调到 10 秒以上。
# 短时间监控,抓 5 秒 timeout 5 redis-cli -h 127.0.0.1 -p 6379 -a your_password monitor | head -100逻辑说明:timeout 5让命令 5 秒后自动结束,避免一直挂着。head -100只看前 100 条。输出里如果看到大量KEYS或INFO,就是工具的问题。
参数说明:monitor本身有性能开销,只用于短时排查。生产环境建议在从库上做,或者业务低峰期做。
4.4 现象:集群模式下部分 key 看不到
原因:工具只连了集群的一个节点,没有做槽位路由。集群的 key 按 CRC16 分散在多个节点,只连一个节点只能看到那个节点上的 key。
解决:确认工具支持集群模式,连接时填多个种子节点。如果工具不支持,可以用redis-cli -c的集群模式手动查,或者用支持集群的客户端库自己写脚本遍历所有节点。
from redis.cluster import RedisCluster rc = RedisCluster(startup_nodes=[ {"host": "127.0.0.1", "port": "7000"}, {"host": "127.0.0.1", "port": "7001"}, ], password="your_password") # 遍历所有主节点 for node in rc.get_primaries(): print("node:", node.host, node.port) # 在该节点上 scan cursor = 0 while True: cursor, keys = node.scan(cursor=cursor, count=100) for k in keys[:5]: print(" key:", k) if cursor == 0: break逻辑说明:get_primaries返回所有主节点,每个主节点单独scan。这样能覆盖所有槽位。
参数说明:startup_nodes至少填两个,避免单点。count=100控制批量。
4.5 现象:TLS 连接报证书错误
原因:Redis 6 以后支持 TLS,但工具可能没加载正确的 CA 证书,或者证书里的 CN/SAN 和连接地址不匹配。
解决:确认工具支持 TLS,并且填了 CA 证书路径。如果是自签证书,需要把 CA 证书导入工具的信任库。连接地址要用证书里签的域名,不能用 IP,除非证书里签了 IP SAN。
# 用 redis-cli 测试 TLS 连接 redis-cli -h redis.example.com -p 6379 --tls \ --cacert /path/to/ca.crt \ --cert /path/to/client.crt \ --key /path/to/client.key \ ping逻辑说明:--tls开启 TLS,--cacert指定 CA 证书,--cert和--key是客户端证书(如果启用了双向认证)。ping返回PONG说明连接成功。
参数说明:如果服务端只要求单向认证,--cert和--key可以省略。--cacert必须是 PEM 格式。
5. 进阶技巧:用 SCAN 游标做增量导出和 key 空间分析
5.1 为什么不要用 KEYS 而要用 SCAN 做导出
KEYS *会一次性遍历所有 key 并返回,时间复杂度 O(N),在百万级 key 的库上会阻塞 Redis 主线程数秒甚至数十秒。SCAN用游标分批返回,每次只处理一小部分,虽然总时间可能更长,但不会造成长时间阻塞。做 key 导出、key 空间分析、批量 TTL 检查,都应该用SCAN。
SCAN有几个特性要记住:游标从 0 开始,返回 0 表示迭代结束;COUNT是提示值不是精确值;在迭代过程中如果有 key 增删,可能漏掉或重复,这是允许的。所以导出场景下,如果要求精确,需要在业务低峰期做,或者接受少量误差。
5.2 一个完整的增量导出脚本
下面这个脚本把匹配前缀的 key 分批导出到文件,支持断点续传(记录游标):
import redis import json import os r = redis.Redis(host="127.0.0.1", port=6379, password="your_password") def export_keys(pattern, out_file, cursor_file, batch=200): # 读取上次的游标,支持断点续传 cursor = 0 if os.path.exists(cursor_file): with open(cursor_file) as f: cursor = int(f.read().strip()) total = 0 with open(out_file, "a") as out: while True: cursor, keys = r.scan(cursor=cursor, match=pattern, count=batch) for k in keys: ktype = r.type(k).decode() ttl = r.ttl(k) # 只导出元信息,不导出 value,避免大 value 撑爆文件 record = { "key": k.decode(errors="replace"), "type": ktype, "ttl": ttl, } out.write(json.dumps(record, ensure_ascii=False) + "\n") total += 1 # 每批写一次游标 with open(cursor_file, "w") as f: f.write(str(cursor)) if cursor == 0: break print(f"exported {total} keys") export_keys("user:*", "keys_export.jsonl", "scan_cursor.txt")逻辑说明:scan的游标每次迭代后更新,写入cursor_file。如果脚本中断,下次从上次游标继续。导出的是 JSONL 格式,每行一个 JSON 对象,方便后续用jq或 Python 处理。
参数说明:batch=200是每次 SCAN 的提示数量,可以根据网络延迟调整,内网可以到 1000。errors="replace"处理非 UTF-8 的 key 名,避免解码报错。只导出元信息不导出 value,是因为 value 可能很大,导出后文件会爆炸。
5.3 用导出的数据做 key 空间分析
导出后可以用 pandas 做分析,看 key 的类型分布、TTL 分布、前缀分布:
import json import pandas as pd from collections import Counter records = [] with open("keys_export.jsonl") as f: for line in f: records.append(json.loads(line)) df = pd.DataFrame(records) print("总 key 数:", len(df)) print("\n类型分布:") print(df["type"].value_counts()) print("\nTTL 分布:") # 把 ttl 分桶 df["ttl_bucket"] = pd.cut(df["ttl"], bins=[-2, -1, 0, 3600, 86400, 604800, float("inf")], labels=["不存在", "永不过期", "1小时内", "1天内", "7天内", "7天以上"]) print(df["ttl_bucket"].value_counts()) print("\n前缀分布 top10:") prefixes = df["key"].str.split(":").str[0] print(Counter(prefixes).most_common(10))逻辑说明:value_counts统计各类型数量。pd.cut把 TTL 分桶,-2表示 key 不存在(导出和查询之间被删了),-1表示永不过期。前缀分布用split(":")取第一段。
参数说明:分桶边界按业务调整,比如会话类 key 可能 1 小时内居多,缓存类可能 1 天居多。most_common(10)取前 10 个前缀。
5.4 一个我常犯的错误
有次我在生产库上直接跑导出脚本,忘了加match参数,结果SCAN遍历了整个库,虽然没阻塞,但导出了几十万条记录,文件几百 MB,分析脚本跑了十分钟。从那以后我每次跑SCAN类脚本,都强制先加match前缀,并且先count=10试跑一次看输出量。另外游标文件一定要写,不然中断了就得从头来。希望这些能帮到你,少走点我踩过的弯路。
本文还有配套的精品资源,点击获取