
作者:贲绍华,爱可生研发中心工程师,负责项目的需求与维护工作。其他身份:柯基铲屎官。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 2000 字,预计阅读需要 6 分钟。
1背景
架构说明
为了方便说明,架构简化为:一主一从一哨兵,哨兵监控的主从名称为[ms]。
master [172.20.134.2] salve [172.20.134.3] sentinel [172.20.134.4]
故障现象
在使用 Redis 7.4.0 版本并采用哨兵主从架构的情况下,当主实例发生故障后,哨兵决策异常。
21903:X 06 Dec 2024 15:53:04.164 * +slave slave 172.20.134.3:6379 172.20.134.3 6379 @ ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:53:04.168 * Sentinel new configuration saved on disk
21903:X 06 Dec 2024 15:54:15.842 # +sdown master ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:54:15.842 # +odown master ms 172.20.134.2 6379 #quorum 1/1
21903:X 06 Dec 2024 15:54:15.842 # +new-epoch 1
21903:X 06 Dec 2024 15:54:15.842 # +try-failover master ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:54:15.846 * Sentinel new configuration saved on disk
21903:X 06 Dec 2024 15:54:15.846 # +vote-for-leader 26189743b4f015611f11d777cbe1df08aaab6c8a 1
21903:X 06 Dec 2024 15:54:15.846 # +elected-leader master ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:54:15.846 # +failover-state-select-slave master ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:54:15.918 # -failover-abort-no-good-slave master ms 172.20.134.2 6379
21903:X 06 Dec 2024 15:54:15.977 * Next failover delay: I will not start a failover before Fri Dec 6 16:00:16 2024
21903:X 06 Dec 2024 16:00:16.375 # +new-epoch 2
21903:X 06 Dec 2024 16:00:16.375 # +try-failover master ms 172.20.134.2 6379
21903:X 06 Dec 2024 16:00:16.390 * Sentinel new configuration saved on disk
21903:X 06 Dec 2024 16:00:16.390 # +vote-for-leader 26189743b4f015611f11d777cbe1df08aaab6c8a 2
21903:X 06 Dec 2024 16:00:16.390 # +elected-leader master ms 172.20.134.2 6379
21903:X 06 Dec 2024 16:00:16.390 # +failover-state-select-slave master ms 172.20.134.2 6379
21903:X 06 Dec 2024 16:00:16.462 # -failover-abort-no-good-slave master ms 172.20.134.2 6379
21903:X 06 Dec 2024 16:00:16.528 * Next failover delay: I will not start a failover before Fri Dec 6 16:06:16 2024
通过日志观察可知,当主实例(172.20.134.2)故障后,哨兵依旧继续选举故障的主实例为新主。但此时应为主实例进程已经被 kill
了,该阶段动作会持续执行相同的内容。
2排查过程
网络检查
通过 ping
与 telnet
命令,检查【哨兵节点->Redis 实例节点间】的网络情况。网络正常,结果符合预期。
确认哨兵配置与日志是否正常
检查哨兵配置文件 sentinel.conf
,检查内容包括:

查看 Redis 实例配置文件 redis.conf
,检查内容包括:


检查后并尝试使用 ACL 用户 markus 进行实例的连接测试,结果均符合预期。
哨兵内主实例的状态
使用 redis-cli 连接到哨兵节点,执行 SENTINEL masters
命令,查看主节点的状态信息。

发现主实例的 flags 为 s_down,o_down,disconnected,符合预期。
哨兵内从实例的状态
执行命令 SENTINEL SLAVES ms
,查看从节点的状态信息。

发现从实例的 flags 也同样处于 disconnected 状态。
状态说明
s_down(Subjectively Down):单个哨兵节点的主观下线状态
定义:s_down 是哨兵节点对某个 Redis 实例的主观下线状态。 触发条件:当一个哨兵节点在一定时间内无法与某个 Redis 实例建立连接,或者无法从该实例获取有效的回复时,该哨兵节点会将该实例标记为 s_down。 作用:s_down 状态是一个局部判断,每个哨兵节点独立进行判断。如果多个哨兵节点都报告同一个实例为 s_down,则可能会触发进一步的处理。
o_down(Objectively Down):多个哨兵节点达成共识后的客观下线状态
定义:o_down 是哨兵系统对某个 Redis 实例的客观下线状态。 触发条件:当大多数哨兵节点(超过配置的 quorum
值)都认为某个 Redis 实例处于 s_down 状态时,哨兵系统会将该实例标记为 o_down。作用:o_down 状态是一个全局判断,表示整个哨兵系统确认该实例已经不可用。一旦某个实例被标记为 o_down,哨兵系统会启动故障转移流程,尝试选举一个新的主节点。
disconnected:哨兵节点与 Redis 实例的连接断开状态
定义:disconnected 状态表示哨兵节点与某个 Redis 实例的连接已断开。 触发条件:当哨兵节点在一定时间内无法与某个 Redis 实例建立连接时,会将该实例标记为 disconnected。 作用:disconnected 状态通常会导致哨兵节点对该实例进行更频繁的检查,以尽快确认其实际状态。如果多次尝试连接失败,哨兵节点可能会将该实例标记为 s_down,进而可能触发 o_down。
哨兵配置项
down-after-milliseconds:配置哨兵节点在多长时间内没有收到 Redis 实例的回复后将其标记为 s_down。 quorum:配置需要多少个哨兵节点报告某个实例为 s_down 才能将其标记为 o_down。
相互关系
disconnected -> s_down -> o_down
:通常情况下,当哨兵节点发现与某个 Redis 实例的连接断开时,会先将其标记为 disconnected。如果多次尝试连接失败,哨兵节点会将该实例标记为 s_down。如果多个哨兵节点都报告同一个实例为 s_down,则哨兵系统会将该实例标记为 o_down。
3原因说明
从目前线索来看,已排除网络端口异常、账号密码信息不正确的场景,Slave 实例的 flags=disconnected
是最可能引起无法正常决策进行故障转移的原因。
在 Redis 6.0 版本之后引入的 ACL(Access Control List)机制,在 >=Redis 6.2 的版本上,增加了对【发布/订阅】权限的支持。
# 官方文档:https://redis.io/docs/latest/operate/rs/7.4/security/access-control/redis-acl-overview/#pubsub-channels
Pub/sub channels
The & prefix allows access to pub/sub channels (only supported for databases with Redis version 6.2 or later).
To limit access to specific channels, include resetchannels before the allowed channels:
在本次实验的版本 Redis 7.4.0 上,创建用户后默认的 Channel 权限被重置为了 resetchannels,哨兵无法通过订阅 channel 来获取主从实例的状态信息从而导致了该现象的产生。
# 官方文档:https://redis.io/docs/latest/operate/rs/7.4/security/access-control/redis-acl-overview/#default-pubsub-permissions
Redis database version 6.2 introduced pub/sub ACL rules that determine which pub/sub channels a user can access.
The configuration option acl-pubsub-default, added in Redis Enterprise Software version 6.4.2, determines the cluster-wide default level of access for all pub/sub channels. Redis Enterprise Software uses the following pub/sub permissions by default:
For versions 6.4.2 and 7.2,
acl-pubsub-default is permissive (allchannels or &*) by default to accommodate earlier Redis versions.
In future versions,
acl-pubsub-default will change to restrictive (resetchannels). Restrictive permissions block all pub/sub channels by default, unless explicitly permitted by an ACL rule.
If you use ACLs and pub/sub channels, you should review your databases and ACL settings and plan to transition your cluster to restrictive pub/sub permissions in preparation for future Redis Enterprise Software releases.
Sentinel 检测机制说明
Redis 哨兵是通过发布/订阅(pub/sub)机制来检测和管理 Redis 实例的状态。这种机制使得哨兵节点之间以及哨兵节点与 Redis 实例之间能够高效地通信,及时发现和响应故障。
Pub/Sub Channel 的作用
在 Redis 哨兵系统中,哨兵节点通过一系列预定义的频道(Channels)来交换信息。这些频道主要用于以下几个目的:
检测实例状态:哨兵节点通过频道接收其他哨兵节点和 Redis 实例的状态信息。 协调故障转移:哨兵节点通过频道协商和决定哪个哨兵节点负责执行故障转移操作。 通知变更:哨兵节点通过频道通知其他哨兵节点和客户端关于主从切换等重要事件。
从 Redis 实例的 redis.conf
配置文件中可知,Pub/Sub Channel 权限为[resetchannels]。

将其调整为[&*]
后进行复现重试,发现故障现象被解决。
本文关键字:#Redis# #哨兵# #Sentinel# #故障分析#
阅读推荐
技术分享 | 一个案例总结 MongoDB 与 Redis 主从同步问题
故障分析 | redis cluster 从库无法自动恢复同步案例一则
技术分享 | 基于 MySQL 多通道主主复制的机房容灾方案
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource
🔗 商业支持:https://www.actionsky.com/sqle
微信扫描小程序码,进行在线咨询预约:

商业支持团队联系方式如下:
400-820-6580 / 13916131869 / 18930110869





