jedis针对redis sentinel给出了一个JedisSentinelPool,jedis给出了很多的构造方法,其中比较全的是下面这个,注意:这个连接池争对的连接还是主节点:
public JedisSentinelPool(String masterName, Set<String> sentinels,final GenericObjectPoolConfig poolConfig, final int connectionTimeout,final int soTimeout,final String password, final int database,final String clientName)
具体参数含义如下:
masterName——主节点名。
sentinels——Sentinel节点集合。
poolConfig——common-pool连接池配置。
connectTimeout——连接超时。
soTimeout——读写超时。
password——主节点密码。(这个是主节点密码,而不是redis sentinel的密码)
database——当前数据库索引
clientName——客户端名
但是通常我们会使用更简单的构造方法:
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName,sentinelSet, poolConfig, timeout, password);
此时timeout既代表连接超时又代表读写超时。
样例代码如下所示:
package com.gildata.duplicateandtagtest.redis;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* Created by LiChao on 2019/2/11
*/
public class SentinelJedisPool {
private static JedisSentinelPool pool = null;
//可用连接实例的最大数目,默认为8;
//如果赋值为-1,则表示不限制,如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)
private static Integer MAX_TOTAL = 1024;
//控制一个pool最多有多少个状态为idle(空闲)的jedis实例,默认值是8
private static Integer MAX_IDLE = 200;
//等待可用连接的最大时间,单位是毫秒,默认值为-1,表示永不超时。
//如果超过等待时间,则直接抛出JedisConnectionException
private static Integer MAX_WAIT_MILLIS = 10000;
//客户端超时时间配置
private static Integer TIMEOUT = 10000;
//在borrow(用)一个jedis实例时,是否提前进行validate(验证)操作;
//如果为true,则得到的jedis实例均是可用的
private static Boolean TEST_ON_BORROW = true;
//在空闲时检查有效性, 默认false
private static Boolean TEST_WHILE_IDLE = true;
//是否进行有效性检查
private static Boolean TEST_ON_RETURN = true;
/**
* 创建连接池
*/
private static void createJedisPool() {
JedisPoolConfig config = new JedisPoolConfig();
/*注意:
在高版本的jedis jar包,比如本版本2.9.0,JedisPoolConfig没有setMaxActive和setMaxWait属性了
这是因为高版本中官方废弃了此方法,用以下两个属性替换。
maxActive ==> maxTotal
maxWait==> maxWaitMillis
*/
config.setMaxTotal(MAX_TOTAL);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT_MILLIS);
config.setTestOnBorrow(TEST_ON_BORROW);
config.setTestWhileIdle(TEST_WHILE_IDLE);
config.setTestOnReturn(TEST_ON_RETURN);
String masterName = "mymaster";
Set<String> sentinels = new HashSet<String>();
sentinels.add(new HostAndPort("192.168.0.31",26379).toString());
sentinels.add(new HostAndPort("192.168.0.32",26379).toString());
sentinels.add(new HostAndPort("192.168.0.33",26379).toString());
String password = "1234@abcd";
pool = new JedisSentinelPool(masterName, sentinels, config, TIMEOUT,password);
}
private static synchronized void poolInit() {
if (pool == null)
createJedisPool();
}
/**
* 获取一个redis对象
* @return
*/
public static Jedis getJedis() {
if (pool == null)
poolInit();
return pool.getResource();
}
}
注意:
样例代码中的password是主节点的密码,而不是redis sentinel的密码,之前讲过redis sentinel也可以设置密码(传送门),如果使用jedis去连接的redis sentinel带有密码,那么会出现权限不足的问题,因为jedis预留的password参数时争对主节点的,所以如果主节点存在密码,切记在安装redis sentinel的时候不要给redis sentinel设置密码,否则jedis是连接不上的。
测试代码:
@Test
public void testSentinel(){
Jedis jedis = null;
try{
jedis = SentinelJedisPool.getJedis();
jedis.set("sentinel","hello sentinel");
}catch (Exception e){
e.printStackTrace();
} finally {
if(jedis!=null){
jedis.close();
}
}
}
执行日志可以看出,此时的主节点是192.168.0.33
16:15:37.121 [main] INFO redis.clients.jedis.JedisSentinelPool - Trying to find master from available Sentinels...
16:15:37.125 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Connecting to Sentinel 192.168.0.31:26379
16:15:37.170 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Found Redis master at 192.168.0.33:6380
16:15:37.171 [main] INFO redis.clients.jedis.JedisSentinelPool - Redis master running at 192.168.0.33:6380, starting Sentinel listeners...
16:15:37.261 [main] INFO redis.clients.jedis.JedisSentinelPool - Created JedisPool to master at 192.168.0.33:6380
hello sentinel
通过info sentinel查看主节点确实是192.168.0.33
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.0.33:6380,slaves=2,sentinels=3
手动切换主节点
127.0.0.1:26379> sentinel failover mymaster
OK
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.0.31:6380,slaves=2,sentinels=3
此时主节点变为了192.168.0.31,再次执行测试用例,执行日志如下:
16:32:53.315 [main] INFO redis.clients.jedis.JedisSentinelPool - Trying to find master from available Sentinels...
16:32:53.320 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Connecting to Sentinel 192.168.0.31:26379
16:32:53.369 [main] DEBUG redis.clients.jedis.JedisSentinelPool - Found Redis master at 192.168.0.31:6380
16:32:53.370 [main] INFO redis.clients.jedis.JedisSentinelPool - Redis master running at 192.168.0.31:6380, starting Sentinel listeners...
16:32:53.463 [main] INFO redis.clients.jedis.JedisSentinelPool - Created JedisPool to master at 192.168.0.31:6380
hello sentinel
主节点变为了192.168.0.31,这就是redis sentinel的好处,它能够主动通知应用程序主节点发生了变更,应用程序不需要做任何变化。