Sentinel+KeyDB集群主节点故障切换时应用未切换主连接的问题
从你的描述来看,KeyDB主节点故障时go-redis客户端能正常感知并切换,但单个Sentinel节点故障时,客户端仅输出了丢弃PubSub连接的日志,这里大概率是客户端没有及时更新可用Sentinel列表,或是后续故障处理逻辑存在疏漏,我给你几个排查和解决的方向:
1. 优先检查go-redis版本兼容性
旧版本的go-redis在Sentinel节点故障场景下,可能存在无法自动刷新可用Sentinel地址列表的bug。建议你升级到最新稳定版(比如v9.x系列),新版本针对Sentinel集群的故障容错逻辑做了不少优化,能更好地适配KeyDB的集群特性。
2. 强化客户端的Sentinel重试与刷新配置
你可以在FailoverOptions中增加相关参数,强制客户端定期刷新Sentinel列表,同时提升连接重试的容错性:
import "time" client := redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: "master", SentinelAddrs: []string{"addr1:26379","addr2:26379","addr3:26379"}, SentinelPassword: "pass", Password: "pass", // 配置Sentinel连接的最大重试次数 SentinelRetryMax: 3, // 每10秒自动刷新一次可用Sentinel节点列表 SentinelRefreshInterval: 10 * time.Second, // 开启连接池健康检查,及时清理无效连接 PoolSize: 10, MinIdleConns: 2, IdleCheckFrequency: 5 * time.Second, })
3. 验证Sentinel集群的共识机制配置
确保3个Sentinel节点的quorum参数设置为2(这是3节点集群的最优配置),这样当单个Sentinel故障时,剩余节点能正常达成共识,正确推送主节点状态变更。你可以通过Sentinel命令验证集群状态:
redis-cli -h addr2 -p 26379 -a pass SENTINEL masters
查看输出中master节点的状态是否正常,以及集群内可用Sentinel的数量是否符合预期。
4. 添加错误回调主动处理连接异常
你看到的redis: discarding bad PubSub connection: EOF日志,说明客户端与故障Sentinel的PubSub连接断开了,但正常情况下客户端应自动切换到其他可用节点建立新连接。如果没有自动触发,你可以添加错误回调手动刷新Sentinel列表:
import "log" client.AddHook(&redis.Hook{ OnError: func(err error) { log.Printf("Redis客户端异常: %v", err) // 手动触发Sentinel列表刷新 client.RefreshSentinels() }, })
5. 模拟故障进行完整测试
手动停止其中一个Sentinel节点,然后主动触发KeyDB主节点故障,观察客户端是否能正常切换到新主节点。如果无法切换,说明客户端没有正确使用剩余的Sentinel节点,这时候需要重点排查客户端的Sentinel列表刷新逻辑是否生效。
备注:内容来源于stack exchange,提问作者Sergey Klimov

