在Redis Sentinel环境下,jedis该如何配置
在Redis主从复制架构中,如果master出现了故障,则需要人工将slave提升为master,同时,通知应用侧更新master的地址。这样方式比较低效,对应用侧影响较大。
为了解决这个问题,Redis 2.8中推出了自己的高可用方案Redis Sentinel。
Redis Sentinel架构图如下:
默认情况下,每个Sentinel节点会以每秒一次的频率对Redis节点和其它的Sentinel节点发送PING命令,并通过节点的回复来判断节点是否在线。
如果在down-after-millisecondes毫秒内,没有收到有效的回复,则会判定该节点为主观下线。
如果该节点为master,则该Sentinel节点会通过sentinel is-master-down-by-addr命令向其它sentinel节点询问对该节点的判断,如果超过<quorum>个数的节点判定master不可达,则该sentinel节点会将master判断为客观下线。
这个时候,各个Sentinel会进行协商,选举出一个领头Sentinel,由该领头Sentinel对master节点进行故障转移操作。
故障转移包含如下三个操作:
1. 在所有的slave服务器中,挑选出一个slave,并将其转换为master。
2. 让其它slave服务器,改为复制新的master。
3. 将旧master设置为新master的slave,这样,当旧的master重新上线时,它会成为新master的slave。
以上的所有操作对业务都是透明的,当新的master上线后,Sentinel会自动将这个变化实时通知给业务方。
那么,业务侧又该如何配置,才能扑捉到这个变化呢?
其实,这个主要取决于Redis客户端工具是否支持Redis Sentinel,对于支持的客户端工具来说,如Jedis,
只需将连接字符串设置为Sentinel地址即可。
下面,给出了一个测试代码,并模拟了master发生故障,业务侧是如何处理的?
代码如下:
package com.victor_02; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool; public class JedisSentinelTest { public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub Set<String> sentinels = new HashSet<String>();
sentinels.add("192.168.244.10:26379");
sentinels.add("192.168.244.10:26380");
sentinels.add("192.168.244.10:26381"); JedisSentinelPool jedisSentinelPool = new JedisSentinelPool("mymaster", sentinels);
Jedis jedis = null;
while (true) {
Thread.sleep(1000); try {
jedis = jedisSentinelPool.getResource(); Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String format_now = dateFormat.format(now); jedis.set("hello", "world");
String value = jedis.get("hello");
System.out.println(format_now + ' ' + value);
} catch (Exception e) {
System.out.println(e);
} finally {
if (jedis != null)
try {
jedis.close();
} catch (Exception e) {
System.out.println(e);
}
}
} }
}
模拟故障:
# ./redis-cli -p
127.0.0.1:> shutdown
上述代码的输出如下:
四月 16, 2017 10:39:44 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
四月 16, 2017 10:39:44 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.244.10:6380, starting Sentinel listeners...
四月 16, 2017 10:39:44 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.244.10:6380
2017/04/16 22:39:45 world
2017/04/16 22:39:46 world
2017/04/16 22:39:47 world
2017/04/16 22:39:48 world
2017/04/16 22:39:49 world
2017/04/16 22:39:50 world
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Software caused connection abort: recv failed
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
四月 16, 2017 10:40:21 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.244.10:6381
四月 16, 2017 10:40:21 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.244.10:6381
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
2017/04/16 22:40:22 world
2017/04/16 22:40:23 world
2017/04/16 22:40:24 world
2017/04/16 22:40:25 world
2017/04/16 22:40:26 world
从上述输出可以看出,在master发生故障前,业务侧最后一次正常处理(22:39:50),到再次正常处理是(22:40:22),中间经过了32s。
而其中30s被用来判断master节点是否主观下线(由down-after-milliseconds来指定),整个切换的过程还是比较高效的。
最新文章
- C语言各种标准的
- Oracle常用监控SQL
- vue model双向绑定
- JMeter的定时器
- JAVA_JSON
- 从源码剖析一个Spark WordCount Job执行的全过程
- HDU ACM 1088 Write a simple HTML Browser
- 音频软件开发中的debug方法和工具
- centos系统php5.6版本安装gd扩展库
- Java 多线程 - 生产者消费者问题
- 第37章 资源所有者密码验证(Resource Owner Password Validation) - Identity Server 4 中文文档(v1.0.0)
- Go语言函数相关
- 实战Google深度学习框架-C5-MNIST数字识别问题
- CentOS7.5下MYSQL8.0.11
- char和varchar、浮点数和定点数
- Spring Boot实战系列-----------邮件发送
- leetcode第一刷_N-Queens II
- 微信公众号开发被动回复用户消息,回复内容Content使用了";\n";换行符还是没有换行
- 手把手教你学node.js 之使用 eventproxy 控制并发
- Tomcat项目部署问题记录
热门文章
- 错误 frm-40654 记录已经被另一个用户更新,重新查询以查看修改
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(一):高清屏显示和UIKit
- CoordinatorLayout 自定义Behavior并不难,由简到难手把手带你撸三款!
- (NO.00004)iOS实现打砖块游戏(四):砖块类的实现
- Android进阶(二十三)Android开发过程之实例讲解
- App会取代网站吗?
- Spark-SQL连接MySql关系型数据库
- Android万能适配器Adapter-android学习之旅(74)
- 【一天一道LeetCode】#53. Maximum Subarray
- 69个Spring面试题