在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来指定),整个切换的过程还是比较高效的。

在Redis Sentinel环境下,jedis该如何配置的更多相关文章

  1. Redis Sentinel 情况下bind地址设置

    Redis Sentinel 情况下bind地址设置 1个master,2个slave,3个sentinel的情况下,注意bind地址的时候不要写0.0.0.0,会导致绑定多个地址, 然后sentin ...

  2. redis 在Linux下的安装与配置

    redis在Linux下的安装与配置 by:授客  QQ:1033553122 测试环境 redis-3.0.7.tar.gz 下载地址: http://redis.io/download http: ...

  3. libCURL开源库在VS2010环境下编译安装,配置详解

    libCURL开源库在VS2010环境下编译安装,配置详解 转自:http://my.oschina.net/u/1420791/blog/198247 http://blog.csdn.net/su ...

  4. 联想电脑win7旗舰版环境下的如何成功配置AppServ

    联想电脑win7旗舰版环境下的如何成功配置AppServ 毕业设计中需要用Mysql数据库,并且想找一个方便Mysql数据库编程的开发工具,百度搜索了一下,AppServ集成环境安装包能快速搭建环境. ...

  5. 实验七:Xen环境下cirrOS的安装配置

    实验名称: Xen环境下cirrOS的安装配置 实验环境: 这里的cirrOS和实验六中的busybox的启动方式相同,唯一的区别就是我们使用的cirrOS镜像中,已经包含了根文件系统.内核文件以及r ...

  6. 【转】mysql8.0 在window环境下的部署与配置

    [转]mysql8.0 在window环境下的部署与配置 今天在阿里云window服务器上配置mysql环境,踩了一些坑,分享出来.需要的朋友可以看看.额,或许有人要吐槽我为什么不在linux上去配置 ...

  7. Linux环境下NodeJS的安装配置(HelloWorld)

    Linux环境下NodeJS的安装配置(HelloWorld) 最简单的环境安装,测试helloworld.给初学者!! 安装脚本,请仔细阅读逐行执行: #!/bin/bash #检查是否已经安装 r ...

  8. GITHUB个人博客搭建-Pelican 在Windows环境下的安装及配置

    GITHUB个人博客搭建-Pelican 在Windows环境下的安装及配置 前言 此篇博客主要为Pelican在Windows平台下的配置安装所写,在此过程中主要参考资料烟雨林博客.poem_of_ ...

  9. Mac 环境下svn服务器的配置

    Mac 环境下svn服务器的配置 本文目录 • 一.创建代码仓库,用来存储客户端所上传的代码 • 二.配置svn的用户权限 • 三.使用svn客户端功能 在Windows环境中,我们一般使用Torto ...

随机推荐

  1. 【一天一道LeetCode】#226. Invert Binary Tree

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源:http ...

  2. LCD正向扫描和反向扫描

    LCD正向扫描和反向扫描 LCD扫描一般分正向扫面和反向扫描,分别针对正装和倒装结构(如下): 有时候提到长边扫描和短边扫描应该是针对横屏和竖屏的设置,大部分显示屏是正向扫描,是否都支持,和玻璃有关, ...

  3. 11.1、Libgdx的音频之音效

    (官网:www.libgdx.cn) 音效通常是比较小的音频文件,通常是几秒钟的长度.通常用在特定的游戏事件中,比如跳跃或者射击. 音效可以保存为多种格式.Libgdx支持MP3.OGG和WAV文件. ...

  4. python的sys模块

    Sys模块函数之多,我只能选取自己认为比较实用的一些函数列在此处.借马云找员工的说法,"找最合适的而不是最天才的",这句话,我个人觉得在很多方面都能适应,学习也不在话下.Sys模块 ...

  5. [WinForm]最小化到系统托盘,右键退出

    1.拉出一个notifyIcon1到用户界面,也可以NEW一个 2.拉出一个ContextMenuStrip控件,命名为mymenu,集合中增加退出 3.notifyIcon1的属性ContextMe ...

  6. 【Unity Shaders】Diffuse Shading——创建一个基本的Surface Shader

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  7. Linux共享内存编程实例

    /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间) 从而使得这些进程可以相互通信. 在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编 ...

  8. Git版本控制:Git分支处理

    http://blog.csdn.net/pipisorry/article/details/46958699分支的意义创建分支可以避免提交代码后对主分支的影响,同时也使你有了相对独立的开发环境. 假 ...

  9. R-- Dplyr包

    Dplyr 包应用 1. 筛选 filter() 按照给定的逻辑判断选择出合适的数据子集 fliter(data,year==2015,month==1) 支持对同一对象的任意条件组合 fliter( ...

  10. Ext JS添加子组件的误区

    经常会有人问我,为什么我的Grid不能岁窗口的变得而自动调整.了解后,发现很多人都习惯在渲染子组件的时候将Gird渲染到容器内的一个div里,而这正是问题的所在. 在Ext JS的布局系统中,能控制到 ...