客户端须通过JedisSentinelPool连接哨兵而非直连Redis主节点,传入哨兵地址列表和主节点名(如"mymaster"),由哨兵动态发现当前主节点并监听+switch-master事件自动刷新地址。

客户端怎么连哨兵,而不是直连 Redis?
Redis 哨兵模式下,客户端**不能硬编码主节点地址**,否则主从切换后连接直接失败。必须让客户端通过哨兵发现当前主节点——这是高可用的前提。
以 Jedis 为例,连接方式不是 new Jedis("192.168.217.139", 6379),而是用 JedisSentinelPool,传入哨兵地址列表和主节点名:
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.217.139:26379");
sentinels.add("192.168.217.140:26379");
sentinels.add("192.168.217.141:26379");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
-
"mymaster"必须和哨兵配置中sentinel monitor后的第一个参数完全一致 - 哨兵端口默认是
26379,不是 Redis 的6379;防火墙要放行该端口 - 客户端会自动订阅哨兵的
+switch-master事件,收到通知后刷新内部主节点地址 - 如果只配一个哨兵地址,单点故障时无法获取新主节点——至少配两个,推荐三个
哨兵配置里 quorum 设多少才安全?
quorum 不是哨兵总数,而是“多少个哨兵达成共识才算主节点下线”。设错会导致脑裂或切换延迟。
- 3 个哨兵,
quorum推荐设为2(即 ⌊n/2⌋ + 1) - 设成
1:任意一个哨兵误判就触发故障转移,风险极高 - 设成
3:必须全部哨兵同意,但只要挂掉一个,就再也无法完成切换 - 哨兵之间靠流言协议通信,网络分区时,
quorum是防脑裂的关键阀值
为什么客户端连上了,却读不到刚写入的数据?
这不是哨兵的问题,而是主从复制天然的异步性导致的——写操作在主节点返回成功后,从节点可能还没同步完。尤其在故障转移刚完成时更明显。
- 新主节点是从某个从节点升上来的,它本身可能落后旧主节点几百毫秒甚至几秒
- 客户端如果还在用旧连接池(没及时刷新),可能连到刚被降级的原主节点,而它已只读或拒绝写入
- JedisSentinelPool 默认有连接缓存,建议设置
setTestOnBorrow(true)并配合理超时,避免拿到失效连接 - 业务上强一致性场景,不要依赖哨兵自动切换兜底;需配合重试、版本号或应用层补偿
单机模拟时最常漏掉的三件事
在一台机器上用不同端口跑主从+哨兵,看着能切,但上线就翻车——往往卡在这三个细节:
- 每个 Redis 实例的
bind配置必须是0.0.0.0或具体 IP,不能留空或写127.0.0.1(哨兵跨端口通信会失败) - 从节点必须显式开启只读:
config set slave-read-only yes,否则手动切主后可能出现双写冲突 - 哨兵配置里
sentinel monitor mymaster 127.0.0.1 6379 2是错的——所有节点对外暴露的 IP 必须统一,虚拟机里要用宿主机可访问的真实 IP,比如192.168.217.139
哨兵不负责数据一致性,只管谁当主;它再稳,也救不了配置错的 IP 或没关掉的从库写权限。

















