Redis MONITOR 命令不支持按频道过滤,因其输出为全量无结构日志;grep 方式易误判漏判;推荐用 redis-cli --csv + awk 实时计数,或改用 PUBSUB NUMSUB 定期采样订阅数以低开销监控活跃度。

MONITOR 命令本身不支持按频道过滤
Redis 的 MONITOR 是一个全局命令监听器,它会输出服务器接收到的**每一条**入站命令(包括 PUBLISH、SET、GET 等),但不会区分来源客户端、数据库编号或频道名。你无法通过参数让 MONITOR 只显示某频道的 PUBLISH —— 它天生就是“全量+无结构”的原始日志流。
所以直接执行 redis-cli MONITOR | grep "PUBLISH my:channel" 看似可行,但实际容易漏判或误判,原因如下:
-
PUBLISH命令在MONITOR输出中格式为"PUBLISH" "my:channel" "payload"(带引号、空格分隔),而 payload 里若含my:channel字符串,grep也会匹配到 - 当 payload 是二进制或含换行/特殊字符时,
grep按行处理会截断,导致匹配失败或解析错乱 -
MONITOR输出没有时间戳字段,仅靠 shell 的date插入会因管道延迟失准,无法精确计算频率
用 redis-cli --csv + awk 实现轻量级频道计数
比纯 grep 更可靠的做法是:让 redis-cli 以 CSV 格式输出命令,再用 awk 提取第三列(即频道名),做实时计数。这样避开引号解析和 payload 干扰。
执行以下命令即可每秒打印一次指定频道的发布次数:
redis-cli --csv MONITOR 2>/dev/null | awk -F',' '$2=="\"PUBLISH\"" && $3=="\"my:channel\"" {c++} ENDFILE{print strftime("%H:%M:%S"), c; c=0}'
说明:
-
--csv让redis-cli把MONITOR输出转成逗号分隔的字段(如"1715823496.123","PUBLISH","my:channel","hello") -
$2=="\"PUBLISH\""匹配第二列为字面量"PUBLISH"(含双引号) -
$3=="\"my:channel\""严格匹配第三列(频道名),避免 payload 冲突 -
ENDFILE在每次缓冲刷出时触发(约每秒一次),配合strftime打印当前时间
真正稳定的方案:用 PUBSUB NUMSUB + 定期采样
如果你要监控的是“某个频道是否被高频发布”,其实更合理的指标不是抓 PUBLISH 流量,而是观察该频道的订阅者活跃度变化 —— 因为无订阅者的 PUBLISH 是空耗,通常不构成业务压力。
执行以下命令可每 2 秒检查一次订阅数,并记录突增:
while true; do echo "$(date +%s),$(redis-cli PUBSUB NUMSUB my:channel | awk '{print $2}')"; sleep 2; done >> pubsub_log.csv
后续可用 awk 或 Python 统计单位时间内订阅数变化率,间接反映发布活跃度。这个方法不依赖 MONITOR,无性能开销,且 Redis 原生命令保证原子性。
MONITOR 的代价远超预期
MONITOR 会强制 Redis 将所有命令序列化为字符串并写入输出缓冲区,这在高并发场景下极易打满网络带宽或阻塞主线程。线上环境开启 MONITOR 超过 30 秒,就可能引发延迟毛刺甚至连接超时。
如果你只是想定位“谁在高频发某个频道”,优先考虑:
- 用
CLIENT LIST查找长期活跃的 client id - 用
SLOWLOG GET看是否有慢PUBLISH(通常意味着大 payload) - 在应用层加日志(如 Node.js 的
redis.publish()前打点),比服务端抓包更精准
真要用 MONITOR,务必限制时长、重定向到本地文件、避免管道堆积 —— 否则你还没分析完数据,Redis 先卡住了。


















