登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis Sentinel 故障转移怎样判断主节点已切换

来源:17golang原创

时间:2026-11-02 08:00:21 496浏览 收藏

Redis Sentinel 故障转移后,最容易误判的地方是“查到了一个新地址”就认为切换完成。更稳妥的判断是把三类信息放在一起:Sentinel 通过 master-name 返回的当前主节点地址、目标 Redis 实例报告的角色,以及 Sentinel 记录的配置纪元。三者一致,才适合让客户端更新连接目标。

官方地址:https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/

实战中先查 Sentinel,再连接它返回的地址读取 ROLE 或 INFO replication,最后对照多个 Sentinel 的视图和 config-epoch。只看旧主节点是否恢复、只看一个 Sentinel,或者只看客户端重连成功,都不足以证明主节点已经切换。

先把判断对象限定为同一个 master-name

Sentinel 监控的是一个逻辑主节点名,例如 mymaster,而不是客户端自己起的业务别名。排查时先确认应用配置里的名称与 Sentinel 配置中的名称相同;名称错了,后面的地址、角色和纪元都会变成另一组数据。

这一步的目标不是判断切换,而是保护判断链路的输入。故障转移期间不要把旧主节点的 IP 固定写回应用配置,也不要把某个 Sentinel 的端口误当成 Redis 数据端口。

先查 Sentinel 认为的当前主节点

SENTINEL get-master-addr-by-name 会按照 master-name 返回当前主节点的地址。返回的两行通常分别是 IP 或主机名、端口;它适合回答“客户端下一步应该找谁”,但单独不能回答“切换是否已经完全收敛”。

# 用监控名称查询 Sentinel 当前记录的主节点地址
redis-cli -h 192.0.2.10 -p 26379 SENTINEL get-master-addr-by-name mymaster

# 查看该 master 的状态字段,重点关注 flags、ip、port 和 config-epoch
redis-cli -h 192.0.2.10 -p 26379 SENTINEL master mymaster
Redis Sentinel 中客户端、主节点名、当前主节点地址和配置纪元的静态关系说明图
图1:结构说明图,查看 Sentinel 如何围绕 master-name 维护当前主节点地址;这是静态关系示意,不是运行截图。

重点记录四个值:查询使用的 master-name、返回的当前主节点 IP、当前主节点端口,以及 SENTINEL master 中的 config-epoch。如果多个 Sentinel 返回的地址不同,先把状态记为“视图尚未收敛”,不要急着改客户端。

用角色和纪元确认切换已经完成

拿到 Sentinel 返回的地址后,直接访问这个 Redis 实例,确认它报告自己是主节点。ROLE 的第一个元素可以表明实例角色,INFO replication 则能补充当前复制关系。这里要看的是目标实例本身的状态,不是客户端连接池里残留的旧连接。

# 连接 Sentinel 返回的目标地址,读取实例自报角色
redis-cli -h 192.0.2.21 -p 6379 ROLE

# 查看复制关系,确认目标实例是否已经成为 master
redis-cli -h 192.0.2.21 -p 6379 INFO replication

可以按下面的证据组合判断:

  • Sentinel 返回的地址是新地址,目标实例 ROLE 的角色为 master:说明新主节点已经具备主角色。
  • 旧地址的 ROLE 变为 slave 或 replica,并指向新主节点:说明旧主节点已经被纳入新的复制关系。
  • Sentinel 的 config-epoch 相比切换前发生推进,多个 Sentinel 最终看到同一地址:说明控制面状态正在收敛。
Redis Sentinel 故障转移后旧主节点、新主节点、ROLE、INFO replication 和配置纪元的静态关系说明图
图2:关系说明图,对照实例角色与配置纪元判断主节点切换是否完成;这是静态关系示意,不是运行截图。

注意,config-epoch 是 Sentinel 用来区分配置版本的控制面信息,不等同于业务数据已经同步到某个时间点。它能帮助判断“哪一套主节点视图更新”,不能替代数据一致性检查。

多个 Sentinel 不一致时怎样分级处理

我在排查时会把结果分成三档,而不是把所有异常都叫作“切换失败”。

观察到的组合判断处理建议
多个 Sentinel 同一地址,目标角色为 master切换证据完整让客户端按 Sentinel 重新获取地址,清理旧连接
地址已相同,但目标角色仍未变为 master实例状态尚未收敛暂缓宣布完成,继续读取角色和复制关系
不同 Sentinel 返回不同地址或纪元控制面视图不一致检查 Sentinel 间连通性、仲裁状态和时间点记录

如果应用重连成功但业务仍然写入旧实例,通常说明连接池没有真正刷新,或代码把首次解析到的地址缓存成了永久配置。Sentinel 的职责是提供当前主节点视图,客户端仍需要支持重新解析、断开旧连接和重试策略。

客户端切换时要保留哪些证据

为了让下一次复盘能还原判断,不必保存完整日志,只需在同一时间窗口记录:查询的 Sentinel 地址、master-name、返回的 IP/端口、ROLE 首字段、INFO replication 中的角色摘要、runid(若返回)和 config-epoch。这些字段足以区分“找到了新地址”和“新地址已经成为主节点”。

// 只把 Sentinel 返回的地址当作候选连接目标,不把旧地址永久写死。
func shouldSwitch(sentinelAddr, masterName, role string) bool {
	// 角色判断只回答目标实例当前是否为 master,地址仍应由 Sentinel 查询得到。
	return sentinelAddr != "" && masterName != "" && role == "master"
}

这段判断只是连接层的最小边界示意,真实客户端还应处理超时、连接池清理和重试退避。不要把“函数返回 true”当成 Redis 已经完成数据同步的证明。

常见问题

只执行 SENTINEL get-master-addr-by-name 可以吗?

它适合获取当前连接目标,但不够证明切换完成。至少再读取目标实例角色,并在多个 Sentinel 之间对照地址和配置纪元。

旧主节点恢复后为什么不能继续使用旧地址?

故障转移后旧实例可能已经变成副本。客户端应遵循 Sentinel 的当前主节点视图,不能因为旧地址重新可连接就把写请求发回去。

config-epoch 越大是否代表数据一定更新?

不是。它用于区分 Sentinel 的配置版本;数据复制进度仍应通过实例角色、复制关系和业务侧可接受的一致性策略单独判断。

总结一下:先用同一个 master-name 查询 Sentinel 当前地址,再对目标实例读取 ROLE 或 INFO replication,最后用多个 Sentinel 的地址和 config-epoch 做交叉判断。这样确认的是一条可复盘的切换证据链,而不是某个瞬间的连通性。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>