redis实战第五篇 jedis 连接 redis sentinel详解
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的好处,它能够主动通知应用程序主节点发生了变更,应用程序不需要做任何变化。
- IIS4\IIS5 CGI环境块伪造0day漏洞
- [原创]Fluent NHibernate之旅(四)-- 关系(上)
- 基于流量的OpenSSL漏洞利用检测方法
- [原创]Fluent NHibernate之旅(四)-- 关系(中)
- 华为专家 | 轻量化微服务测试实践
- Android Material Design系列之Navigation Drawer
- [原创]Fluent NHibernate之旅(四)-- 关系(下)
- 一次通过漏洞挖掘成功渗透某网站的过程
- 使用fuzzDB进行web安全测试
- Android Material Design系列之FloatingActionButton和Snackbar
- Fluent Nhibernate之旅(五)--利用AutoMapping进行简单开发
- Android Material Design系列之Toolbar
- Struts2 S2-020在Tomcat 8下的命令执行分析
- Struts2再曝S2-020补丁绕过漏洞 – 万恶的正则表达式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- NSOperationQueue队列中操作依赖相关思考
- 单细胞转录组高级分析一:多样本合并与批次校正
- 10元最多可喝多少瓶啤酒?(不可借酒+可借酒,swift语言实现)
- 单细胞转录组高级分析二:转录调控网络分析
- 关于数组内元素是否会被改变的思考
- 排序之选择排序实现(swift)
- 去除友盟等第三方SDK失败的解决办法(clang: error: no such file or directory:xx)
- iOS踩坑之多代理模式使用注意
- 单细胞转录组高级分析三:细胞通讯分析
- 单细胞转录组高级分析四:scRNA数据推断CNV
- 0808-7.1.1-如何在CDP7.1.1指定Hive SQL的资源池队列
- iOS多线程之GCD、OperationQueue 对比和实践记录
- singleR的7个数据库文件下载失败的解决方案
- Spring Boot 如何快速集成 Redis 哨兵?
- 一行命令实现成“吨”测试数据的转码