因为Sentinel不处理GET/SET等数据命令,仅响应SENTINEL类管理命令;redis.Dial仅支持直连单实例,需先通过Sentinel获取主节点地址再连接。

为什么直接用 redis.Dial 连不上 Sentinel?
因为 Sentinel 和 Redis 实例是两个独立服务:Sentinel 负责监控和故障转移,不处理业务命令;你真正要连的是它推荐的当前主节点(或从节点)。直接把 Sentinel 地址当 Redis 地址传给客户端,会收到 ERR unknown command 或连接后立即断开——Sentinel 响应的是 SENTINEL get-master-addr-by-name 这类管理命令,不是 SET/GET。
用 github.com/go-redis/redis/v8 配 Sentinel 最简路径
官方推荐库 go-redis 内置了 Sentinel 支持,不需要手动轮询或解析 SENTINEL slaves。关键不是“怎么连 Sentinel”,而是“怎么让客户端自动发现并切换主节点”:
- 用
redis.NewFailoverClient,不是NewClient -
MasterName必须和 Sentinel 配置里的sentinel monitor <master-name>完全一致(大小写敏感) -
SentinelAddrs填 Sentinel 的host:port列表,至少填一个在线的,客户端会自动发现其余节点 - 别设
Username或Password在 FailoverOption 里——如果 Redis 实例本身有密码,填在FailoverOptions.Password;如果 Sentinel 有认证(少见),得单独配sentinelPassword
opt := &redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{"10.0.1.10:26379", "10.0.1.11:26379"},
Password: "redis_password", // ← 这是 Redis 实例密码,不是 Sentinel 密码
}
client := redis.NewFailoverClient(opt)
故障转移时会不会丢命令?
不会自动重试,但可以控制行为:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 默认情况下,主节点宕机期间发过去的命令会返回
redis.Nil或redis.Error(如MOVED、ASK不适用 Sentinel 场景,但可能遇到READONLY) - 如果需要自动重试,得自己 wrap
Do或用WithContext配合retryablehttp类逻辑——go-redis不内置重试,避免掩盖真实故障 - 注意
client.Ping(ctx).Err()只检测当前连接是否通,不能代替对主节点可用性的判断;更稳妥的是client.Set(ctx, "health", "ok", 0).Err()
本地开发时连不上,先查这三件事
常见卡点不在 Go 代码,而在环境配置:
- Sentinel 配置里没开
protected-mode no,且bind没包含客户端所在网段(比如只绑了127.0.0.1,但 Go 程序跑在 Docker 容器里) - Redis 实例的
requirepass和 Sentinel 的requirepass是两套配置;如果只给 Redis 设了密码,但没在FailoverOptions.Password里填,就会卡在 AUTH 阶段 - 用
redis-cli -p 26379手动执行SENTINEL get-master-addr-by-name mymaster返回空或错误,说明 Sentinel 根本没监控到主节点——检查sentinel monitor指令里的 IP 是否是 Redis 实例实际监听的地址(不是127.0.0.1)
自动发现依赖 Sentinel 主动上报,不是客户端主动扫描;哪一环断了,整个链路就静默失败。

















