【Redis从入门到精通】第62篇:Redis监视器——MONITOR命令的原理与实战

发布时间:2026/6/5 22:42:39

【Redis从入门到精通】第62篇:Redis监视器——MONITOR命令的原理与实战 上一篇【第61篇】慢查询日志——找出Redis性能瓶颈的利器下一篇【第63篇】分布式锁——用Redis实现高可靠锁的正确姿势运维老王“客户端A说我没写过那个Key客户端B也说没有那到底是谁写的”程序员小李“开启MONITOR看看到底谁在搞鬼。”运维老王“打开了……卧槽这刷屏速度根本看不过来啊”程序员小李“所以说MONITOR是双刃剑用好了抓鬼用不好伤己。”在Redis的调试工具箱中MONITOR命令是一个极其强大的偷窥神器——它能让你实时看到Redis服务器接收到的每一条命令。无论哪个客户端发送的、什么时候发的、发了什么统统无所遁形。但就像X光一样用多了对身体服务器性能是有伤害的。本文将带你深入理解MONITOR的原理、正确用法以及何时该用、何时绝对不该用。一、MONITOR命令的基本使用1.1 命令简介# 开启监视器模式127.0.0.1:6379MONITOR OK# 之后所有客户端发送的命令都会实时显示在这个连接上1716278400.123456[0127.0.0.1:54321]SETuser:1001Alice1716278400.123789[0127.0.0.1:54322]GETuser:10011716278400.124012[0127.0.0.1:54321]LPUSHqueue:taskstask_0011716278400.124345[1192.168.1.100:63790]HSETorder:5001statuspaid1.2 输出格式解析每行MONITOR输出的格式如下1716278400.123456 [0 127.0.0.1:54321] SET user:1001 Alice │ │ │ │ │ │ │ │ │ │ │ └── 参数 │ │ │ │ └── 命令名 │ │ │ └── 数据库编号默认为0 │ │ └── 客户端IP:端口 │ └── 客户端ID可以 CLIENT LIST 查看 └── UNIX时间戳秒.微秒通过这些信息你可以精确地知道谁哪个客户端IP和端口什么时候精确到微秒的时间戳做了什么执行的完整命令和参数1.3 redis-cli --monitor 方式除了在redis-cli里手动输入MONITOR还可以直接用命令行参数# 方式1先连接再MONITORredis-cli127.0.0.1:6379MONITOR# 方式2直接启动时就开启监视redis-cli--monitor# 方式3监视指定数据库redis-cli-n1--monitor# 方式4将输出重定向到文件方便后续分析redis-cli--monitor/tmp/redis_monitor.log# 方式5管道模式读取已有的MONITOR输出做分析redis-cli--monitor|grepuser:二、MONITOR的实现原理2.1 客户端标志位当一个客户端执行MONITOR命令后Redis会在该客户端的flags中设置CLIENT_MONITOR标志位redisClient 结构体中的 flags 字段 ┌──────────────────────────────────────────────────────┐ │ flags │ │ ┌──────┐ ┌──────────┐ ┌──────┐ ┌───────────────────┐│ │ │MASTER│ │SLAVE │ │PUBSUB│ │CLIENT_MONITOR ← 新增││ │ └──────┘ └──────────┘ └──────┘ └───────────────────┘│ └──────────────────────────────────────────────────────┘2.2 monitors链表Redis服务器内部维护了一个monitors链表所有处于MONITOR状态的客户端都会被加入这个链表Redis服务器内存结构 ┌─────────────────────────────────────────────────────┐ │ redisServer │ │ │ │ monitors ── [client_A] ── [client_B] ── NULL │ │ │ │ │ │ MONITOR状态的客户端 │ │ │ 都会被挂到这个链表上 │ │ │ └─────────────────────────────────────────────────────┘ 当客户端执行 MONITOR 命令时 ┌─────────┐ │ MONITOR │── flags | CLIENT_MONITOR │ │── listAddNodeTail(server.monitors, client) └─────────┘2.3 命令执行的窃听流程MONITOR的核心机制是在命令执行前窃听命令信息。具体流程如下命令执行流程简化版 客户端发送命令 │ ▼ ┌───────────────┐ │ 查询缓存/解析 │ └───────┬───────┘ │ ▼ ┌───────────────────────────────────────┐ │ ★ 检查 monitors 链表是否为空 │ │ 如果不为空 │ │ 1. 构建命令信息的字符串 │ │ 2. 遍历 monitors 链表 │ │ 3. 将命令信息发送给每个监视器客户端 │ └───────────────┬───────────────────────┘ │ ▼ ┌───────────────┐ │ 执行命令本身 │ └───────────────┘ │ ▼ ┌───────────────┐ │ 返回结果给客户端│ └───────────────┘关键代码逻辑伪代码// call() 函数 - 命令执行的入口voidcall(redisClient*c,intflags){// ... 前置检查 ...// ★ 如果有监视器把命令信息发给它们if(listLength(server.monitors)0){// 构建监视器输出字符串// 格式: timestamp [db_id client_addr] \cmd\ \arg1\ \arg2\ ...char*monitor_cmdcreateMonitorOutput(c);// 遍历所有监视器客户端逐个发送listNode*ln;listIter li;listRewind(server.monitors,li);while((lnlistNext(li))){redisClient*monitorln-value;// 将命令信息追加到监视器客户端的输出缓冲区addReply(monitor,monitor_cmd);}}// 执行真正的命令c-cmd-proc(c);// ... 后续处理 ...}这里有一个重要的细节MONITOR是在命令执行前发送信息的这意味着即使命令执行失败或被拒绝监视器依然能看到它。三、MONITOR的性能影响这是使用MONITOR之前必须了解的最重要的事情。3.1 性能损耗有多大根据Redis官方的benchmark测试开启MONITOR后Redis的吞吐量大约下降50%MONITOR 对性能的影响 不开启 MONITOR ┌─────────────────────────────────────────┐ │ QPS: ████████████████████████████ 100000│ └─────────────────────────────────────────┘ 开启 1 个 MONITOR 客户端 ┌─────────────────────────────────────────┐ │ QPS: ██████████████████ ~50000 │ └─────────────────────────────────────────┘ 吞吐量下降约 50% 开启 2 个 MONITOR 客户端 ┌─────────────────────────────────────────┐ │ QPS: ████████████ ~33000 │ └─────────────────────────────────────────┘ 下降更多3.2 性能损耗的原因每条命令的额外开销 原始流程 接收命令 ── 执行命令 ── 返回结果 MONITOR流程接收命令 ── 格式化命令信息 ── 发送给监视器1 ── 发送给监视器2 ── 发送给监视器N ── 执行命令 ── 返回结果 额外开销 格式化 N次网络发送 输出缓冲区占用具体影响CPU增加每条命令都需要额外的字符串格式化操作网络带宽翻倍每条命令至少多发送一份数据给监视器内存增加监视器客户端的输出缓冲区可能堆积大量数据客户端延迟增加MONITOR的输出可能挤占网络带宽踩坑提示绝对不要在生产环境的Redis主节点上长时间开启MONITOR。如果确实需要请在从节点上开启且时间尽量短。曾经有运维同学在高峰期对主节点MONITOR了10分钟结果导致整个服务雪崩——这不是段子是真事。四、MONITOR的实际使用场景虽然性能影响大但MONITOR在正确的场景下是无价之宝。4.1 排查未知写入场景某个Key的值突然变了但所有开发都说没碰过。# 步骤1在redis-cli中开启MONITOR过滤特定Keyredis-cli--monitor|grepmystery_key# 输出# 1716278400.123456 [0 192.168.1.50:34567] SET mystery_key 谁改了我一目了然是192.168.1.50:34567这个客户端干的。顺藤摸瓜找到对应的业务服务。4.2 调试客户端行为场景怀疑某个客户端发了多余的命令或者命令格式不对。# 监控特定IP的所有命令redis-cli--monitor|grep192.168.1.50# 监控特定命令redis-cli--monitor|grepHSET4.3 配合DEBUG命令使用# 在一个终端开启MONITORredis-cli--monitor# 在另一个终端模拟慢操作redis-cli DEBUG SLEEP1# 让Redis暂停1秒# MONITOR输出# 1716278400.123456 [0 127.0.0.1:54321] DEBUG SLEEP 1# 模拟服务器重载测试环境使用redis-cli DEBUG RELOAD踩坑提示DEBUG SLEEP和DEBUG RELOAD是调试命令千万不要在生产环境使用它们会阻塞整个Redis进程。4.4 性能分析结合DEBUG SLEEP可以精确测试延迟的影响# 终端1MONITORredis-cli--monitor# 终端2模拟阻塞redis-cli DEBUG SLEEP0.5# 终端3同时发送请求观察延迟redis-cli--latency五、集群模式下的限制在Redis Cluster模式下MONITOR的行为有一些限制Redis Cluster 集群 ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 节点A (主) │ │ 节点B (主) │ │ 节点C (主) │ │ slot 0-5460 │ │ slot 5461- │ │ slot 10923- │ │ │ │ 10922 │ │ 16383 │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ MONITOR在这里 MONITOR在这里 MONITOR在这里 只能看到 只能看到 只能看到 这里的命令 这里的命令 这里的命令 ✗ 无法在一个节点上看到所有命令在集群模式下你需要在每个节点上都开启MONITOR才能看到完整的命令流# 需要对每个节点分别开启MONITORredis-cli-p7000--monitornode_7000.logredis-cli-p7001--monitornode_7001.logredis-cli-p7002--monitornode_7002.logredis-cli-p7003--monitornode_7003.logredis-cli-p7004--monitornode_7004.logredis-cli-p7005--monitornode_7005.log六、更好的替代方案鉴于MONITOR的性能开销较大Redis提供了更轻量的替代方案6.1 对比表格工具功能性能影响适用场景MONITOR实时查看所有命令严重~50% QPS下降临时调试SLOWLOG记录慢命令极小性能问题排查LATENCY MONITOR延迟事件监控小延迟问题排查INFO commandstats命令统计极小了解命令使用模式redis-fainaMONITOR输出分析工具N/A离线分析分析MONITOR捕获的数据AOF日志重放所有写操作无分析离线文件事后审计6.2 LATENCY MONITOR# 开启延迟监控默认关闭127.0.0.1:6379CONFIG SET latency-monitor-threshold100OK# 查看延迟事件127.0.0.1:6379LATENCY LATEST# 查看延迟历史127.0.0.1:6379LATENCY HISTORYcommand# 自动诊断延迟原因127.0.0.1:6379LATENCY DOCTOR6.3 redis-fainaMONITOR的数据分析助手redis-faina是Instagram没错就是那个Instagram开源的MONITOR输出分析工具。它的思路很巧妙——不直接在Redis上实时看MONITOR输出而是把输出保存下来然后离线分析。# 安装pipinstallredis-faina# 使用方式1管道redis-cli--monitor|redis-faina# 使用方式2分析已保存的日志redis-faina /tmp/redis_monitor.log# 输出示例# Top K Prefixes: Top Commands:# users: GET 45.2% (45234)# session: SET 30.1% (30123)# cache: LPUSH 15.3% (15345)# HGETALL 9.4% (9456)## Top Keys:# users:1001:profile GET 12345 calls, avg 0.5ms# session:abc123 SET 9876 calls, avg 0.3ms## Overall Stats:# Total Commands: 100,023# Total Latency: 50.123 seconds# Avg Latency: 0.501 ms# Time Range: 1716278300 - 1716278600 (5 minutes)这种捕获 离线分析的模式完美解决了MONITOR实时查看的两大痛点数据刷太快看不过来 → 工具自动统计汇总在Redis上实时分析影响性能 → 只捕获数据分析在别的机器上进行七、退出MONITOR模式退出MONITOR很简单但有人会因为不知道怎么退而强制关闭终端# 方式1发送QUIT命令推荐127.0.0.1:6379QUIT# 方式2CtrlC# 直接按CtrlC中断连接# 方式3如果是后台运行kill%1# 杀掉后台进程退出后该客户端会从monitors链表中移除Redis恢复正常性能。小结MONITOR是Redis调试的核武器——威力巨大但使用需要谨慎。记住以下要点生产慎用性能损耗约50%只在从节点或低峰期使用替代优先优先用SLOWLOG、LATENCY MONITOR、INFO commandstats短时间用需要MONITOR时抓取几秒数据就够了然后立刻关闭配合工具用redis-faina等工具分析MONITOR输出效率翻倍集群注意每个节点只能看到自己的命令上一篇【第61篇】慢查询日志——找出Redis性能瓶颈的利器下一篇【第63篇】分布式锁——用Redis实现高可靠锁的正确姿势

相关新闻