Redis Sentinel 为 Java 客户端提供了高可用支持,Jedis 2.2.2 及以上版本已内置相关能力。通过查询 Sentinel 获取主节点地址是基础操作,例如执行 sentinel get-master-addr-by-name 命令即可定位当前 Master。
但在实际分片场景中,直接使用 JedisSentinelPool 存在局限。它需要硬编码分片名称,无法自动感知分片间的 Master 切换。一旦某个分片发生主从切换,原有连接池仍指向旧节点,导致请求失败。为此,我们需要一个能动态感知所有分片状态并重建连接池的方案。
这里以 ShardedJedisSentinelPool 为例,看看如何实现这一目标。
核心实现逻辑
初始化阶段,构造函数接收连接池配置、分片 Master 名称列表及 Sentinel 节点集合。关键点在于 initSentinels 方法,它会遍历所有 Sentinel,尝试获取每个分片的 Master 地址。如果全部不可用,会休眠重试,直到成功或达到最大重试次数。这确保了启动时能锁定正确的节点位置。
for (String masterName : masters) {
HostAndPort master = null;
boolean fetched = false;
while (!fetched && sentinelRetry < MAX_RETRY_SENTINEL) {
// 遍历 Sentinel 节点
for (String sentinel : sentinels) {
// 连接并获取主节点信息
List<String> hostAndPort = jedis.sentinelGetMasterAddrByName(masterName);
// 解析并存储主节点地址
}
}
}
监控与故障转移
真正的亮点在于后台线程。每个 Sentinel 都会启动一个 MasterListener 线程,通过 Jedis 的 Pub/Sub API 订阅 +switch-master 频道。当 Sentinel 检测到主从切换时,会推送新 Master 地址。监听线程捕获通知后,根据分片名更新本地缓存,并调用 initPool 重建连接池。对上层应用而言,这个过程完全透明,无需重启服务。
实战应用
配置好连接池后,使用方式与普通 ShardedJedis 类似。注意区分分片名称和 Sentinel 地址。以下是完整的测试类示例:
package com.redis.sentinel.demo;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ShardedJedisSentinelTest {
public static void {
List<String> masters = <>();
masters.add();
masters.add();
Set<String> sentinels = <>();
sentinels.add();
sentinels.add();
(poolConfig, masters, sentinels);
}
}

