
最近因为celery的问题,研究了下redis的stream。
关于redis stream配置不当导致的问题之前很少在网上看到遇到的,正好最近看到这篇文章,转过来。
做运维和开发的同学应该都懂,Redis告警一响,心跳直接漏半拍。
前几天我们就撞上了这么个棘手问题:Redis主从突然切换,新主刚上位又被判定下线。排查到最后才发现,元凶居然是一个堆积了八千多万条消息的Stream。
今天就跟大家复盘整个过程,希望能帮大家避避坑。
早上,监控告警准时炸开:Redis-Server 6379 is stop。
我们的 Redis 架构是一主两从三哨兵,按道理说就算主节点挂了,哨兵也会快速切换,不至于触发服务停止告警。
登录服务器第一件事就是查进程,结果出乎意料:Redis 相关进程全都正常运行。
这就奇怪了,进程没挂,为啥会告警?
在排查问题前,先简单介绍下Redis哨兵架构,帮助理解后续故障链路:
down-after-milliseconds 配置为 5000ms,即节点超过5秒无响应,就会被判定为主观下线。既然进程没问题,那就从日志入手。
翻看哨兵日志后,真相浮出水面:哨兵确实触发了主从切换操作。原主节点123被判定下线,哨兵投票将121切换成新主。但诡异的是,新主上位才6秒,就被标记为 sdown(主观下线)。
91495:X 16 Jan 2026 08:37:59.869 # +new-epoch 13
91495:X 16 Jan 2026 08:37:59.871 # +vote-for-leader 5d8bc4ef7e1ed90ce157d5964fd6d5d85f03052e 13
91495:X 16 Jan 2026 08:38:00.733 # +odown master mymaster 10.191.2.123 6379 #quorum 3/2
91495:X 16 Jan 2026 08:38:00.733 # Next failover delay: I will not start a failover before Fri Jan 16 08:44:00 2026
91495:X 16 Jan 2026 08:38:00.974 # +config-update-from sentinel 5d8bc4ef7e1ed90ce157d5964fd6d5d85f03052e 10.191.2.122 26379 @ mymaster 10.191.2.123 6379
91495:X 16 Jan 2026 08:38:00.974 # +switch-master mymaster 10.191.2.123 6379 10.191.2.121 6379
91495:X 16 Jan 2026 08:38:00.974 * +slave slave 10.191.2.122:6379 10.191.2.122 6379 @ mymaster 10.191.2.121 6379
91495:X 16 Jan 2026 08:38:00.974 * +slave slave 10.191.2.123:6379 10.191.2.123 6379 @ mymaster 10.191.2.121 6379
91495:X 16 Jan 2026 08:38:06.033 # +sdown master mymaster 10.191.2.121 6379
91495:X 16 Jan 2026 08:38:06.033 # +sdown slave 10.191.2.123:6379 10.191.2.123 6379 @ mymaster 10.191.2.121 6379
91495:X 16 Jan 2026 08:38:06.033 # +sdown slave 10.191.2.122:6379 10.191.2.122 6379 @ mymaster 10.191.2.121 6379我们第一反应是网络抖动,但查了服务器的网卡流量、延迟、丢包率、CPU等指标,全都正常,网络和系统问题的嫌疑被排除。
接着检查哨兵配置,down-after-milliseconds 设的是 5000ms,也就是 5 秒超时判定,配置也不算问题。
最后把目光投向 Redis 慢查询日志,这一下直接抓到了关键线索:一条 DEL wxMsg 命令,耗时高达 9.6 秒!
[redis@redis_121:/home/mpay/app/redis/bin]>> ./redis-cli -h 10.191.2.121 -a xxxxxxxxx
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
10.191.2.45:6379> SLOWLOG get
2) 1) (integer) 2352
2) (integer) 1768526239
3) (integer) 9632634
4) 1) "DEL"
2) "wxMsg"
5) "10.191.3.65:50840"
6) ""9.6秒是什么概念?远超哨兵5秒的超时阈值。Redis是单线程模型,这条慢命令直接把整个服务堵死了。
此时单单查到慢查询还不够,还得弄清楚 wxMsg 这个 key 到底是什么来头。
我们用命令登录 Redis 一探究竟:
10.191.2.121:6379> type wxMsg
stream
10.191.2.121:6379> XLEN wxMsg
(integer) 241
10.191.2.121:6379> XINFO GROUPS wxMsg
1) 1) "name"
2) "stlm"
3) "consumers"
4) (integer) 4
5) "pending"
6) (integer) 83734874这组命令的输出,直接揭开了谜底:
wxMsg 是一个 Stream 类型的 key,主要用来做消息队列。wxMsg 这个 Stream,结果因为 Redis 命令超时直接失败。2026-01-16 98:37:58 [com.xx1.job.core.thread.JobThread#run]-[204]-[xx1-job,JobThread-157-1768523874392]<br>--
..- JobThread Exception: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:31)
at com.xxl.job.core.thread.JobThread.run(JobThread.java:166)
Caused by: org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException:
Command timed out after 2 second (5)至此,整个故障链路就清晰了:
wxMsg Stream 的 stlm 消费组存在海量未确认消费的消息,形成严重的消费堆积。DEL wxMsg 命令,试图删除这个大key。找到根因后,我们立刻和研发确认,得到关键结论:stlm消费组属于历史遗留配置,业务侧已无使用,可以直接删除。 基于这个结论,我们采取了以下措施
复盘完这次故障,我们也总结了几个关键点,分享给大家:
最后,想问下各位同行:你们在运维 Redis 的时候,都遇到过哪些奇葩故障?欢迎在评论区分享你的经历~
公众号:DevOps运维实践
原文地址:https://mp.weixin.qq.com/s/BknJjJonAXfTSKxvB64zGw
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。