客户端实现高可用读写分离的关键在于支持Sentinel协议、自动发现新主节点及正确分发读请求;需选用适配SDK(如JedisSentinelPool、Lettuce、StackExchange.Redis≥2.0、redis-py≥4.0),合理配置quorum和down-after-milliseconds,读操作轮询slave_for获取的动态从节点列表,强一致读必须走主节点。

客户端要真正实现高可用读写分离,关键不在哨兵本身怎么配,而在于客户端是否支持 Sentinel 协议、能否自动发现新主节点、以及是否把读请求正确分发到从节点 —— 哨兵只管选主和通知,不负责路由。
客户端必须使用支持 Sentinel 的 Redis SDK
很多老版本 SDK(比如早期 Jedis 2.x、StackExchange.Redis 1.x)默认只连单点,redis://192.168.1.100:6379 这种直连方式在主节点宕机后会直接报 Connection refused 或 NOAUTH(因密码/地址已变),根本不会触发故障转移逻辑。
- Java 推荐用
JedisSentinelPool或Lettuce(原生支持 Sentinel 自动重连) - .NET 必须用
StackExchange.Redis≥ 2.0,并配置sentinelConnectTimeout和service-name - Python 推荐
redis-py≥ 4.0,用Sentinel类初始化,再调master_for()/slave_for() - 直连
redis-cli -h sentinel-host -p 26379是无效的 —— 它只是连接哨兵进程,不能执行业务命令
sentinel.conf 中 quorum 和 down-after-milliseconds 必须匹配实际网络质量
这两个参数直接影响故障判定是否“太敏感”或“太迟钝”。例如在云环境跨可用区部署时,网络抖动常见,若还沿用默认 down-after-milliseconds 30000,可能一次短暂超时就触发误判;但设得太小(如 500ms)又容易因瞬时丢包导致频繁切换。
-
quorum值必须 ≤ 哨兵总数且 ≥ ⌊N/2⌋+1:3 个哨兵时设为 2,5 个哨兵时设为 3 —— 设成 1 就退化成单点判断,失去“客观宕机”意义 -
down-after-milliseconds建议设为 P99 RTT + 200ms:用redis-cli -h sentinel-ip -p 26379 ping测 100 次取 P99,再加缓冲 -
failover-timeout要大于从节点全量同步耗时,否则切换中途被中止,新主未生效就回滚
读写分离不能靠客户端硬编码 IP,得用哨兵返回的动态拓扑
写操作必须始终走 master_for("mymaster") 获取的连接,读操作应轮询 slave_for("mymaster") 返回的多个从节点。如果手动写死从节点地址(如 redis://192.168.1.101:6379),一旦该从节点在故障转移中被升为主、或被下线,读请求就会失败。
- 每次获取 slave 连接前,SDK 内部会向哨兵发
SENTINEL slaves mymaster,拿到当前存活且状态为online的从节点列表 - 注意
replica-priority配置会影响哨兵返回的从节点顺序,但不等于客户端必须按此顺序读 —— 客户端可自行做负载均衡(如轮询、最小连接数) - 某些 SDK(如旧版 Lettuce)默认关闭从节点读,需显式启用
ReadFrom.SLAVE或ReadFrom.REPLICA
最容易被忽略的是:哨兵不保证从节点数据实时性。异步复制下,从节点可能落后主节点几百毫秒甚至几秒,业务若要求强一致读(如刚写完立刻查),必须强制走主节点 —— 这不是配置问题,是架构约束。


















