redis.dial()不能直接连哨兵,因其仅支持直连单实例,而哨兵不处理数据命令(如get),需先通过sentinel get-master-addr-by-name获取主节点地址再连接;go-redis/v9则通过redis.newfailoverclient()原生支持自动发现与故障转移。

为什么 redis.Dial() 不能直接连哨兵
因为 redis.Dial()(老版 redigo)或 redis.NewClient()(新库如 go-redis)默认只连单个 Redis 实例,而哨兵模式下客户端需要先问哨兵(Sentinel)“当前主节点是谁”,再连过去。直接填哨兵地址会报 ERR unknown command 'GET' 或连接后执行命令失败——哨兵不处理数据命令。
用 go-redis/v9 连哨兵最简可行配置
go-redis 是目前主流选择,v9 版本原生支持哨兵。关键不是换函数,而是换客户端类型和初始化方式:
- 不用
redis.NewClient(),改用redis.NewFailoverClient() -
MasterName必须和 Sentinel 配置里的sentinel monitor <master-name></master-name>完全一致(大小写敏感) -
SentinelAddrs填哨兵地址列表,不是 Redis 地址;端口通常是26379,不是6379 - 别漏掉
Password:如果哨兵本身配了requirepass,这里要填哨兵密码;如果 Redis 主从有密码,还要额外设MasterPassword
opt := &redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{"10.0.1.10:26379", "10.0.1.11:26379"},
Password: "sentinel-pass", // 哨兵认证密码
MasterPassword: "redis-pass", // Redis 实例密码(如有)
}
client := redis.NewFailoverClient(opt)
连接后如何验证是否真走哨兵逻辑
光不报错不代表成功。哨兵模式下 client 应该能自动感知主从切换。验证点有三个:
- 调用
client.Role(),返回值第一个字段应为"master"或"slave",而不是报错或空 - 手动 kill 当前主节点,等 30 秒左右,再查
client.Info("replication"),看role:字段是否已更新 - 日志里搜
redis: switched master(go-redis v9 默认开启 debug 日志时会打)
如果始终连着旧 IP 不切换,大概率是 MasterName 拼错,或哨兵没真正监控到该主节点(可用 redis-cli -p 26379 sentinel masters 在服务器上确认)。
redigo 用户怎么适配哨兵(不推荐但有时绕不开)
redigo 本身不支持哨兵,得自己封装一层:先用 redis.Dial() 连任意一个哨兵,发 SENTINEL GET-MASTER-ADDR-BY-NAME <master-name></master-name> 拿到主节点地址,再用这个地址 dial 新连接。问题在于:
- 没自动重试:主切完你缓存的地址就失效了
- 没连接池管理:每次都要重新 Dial,性能差
- 没故障转移逻辑:比如拿到的主节点其实已下线,你还硬连
真要用 redigo,至少把 “查主节点 + Dial” 封装成带缓存和简单重试的函数,并在每次操作前检查连接健康状态(比如 PING)。但不如直接迁移到 go-redis。
哨兵模式真正的复杂点不在连接代码,而在超时设置和故障响应时机——比如 MinTimeout、MaxRetries 这些 FailoverOptions 字段,线上环境必须根据哨兵的 down-after-milliseconds 和 failover-timeout 来对齐,否则可能提前放弃重试或卡死等待。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











