阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Redis Sentinel环境下配置jedis

109次阅读
没有评论

共计 6452 个字符,预计需要花费 17 分钟才能阅读完成。

在 Redis 主从复制架构中,如果 master 出现了故障,则需要人工将 slave 提升为 master,同时,通知应用侧更新 master 的地址。这样方式比较低效,对应用侧影响较大。

为了解决这个问题,Redis 2.8 中推出了自己的高可用方案 Redis Sentinel。

Redis Sentinel 架构图如下:

Redis Sentinel 环境下配置 jedis

 

默认情况下,每个 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 6380
127.0.0.1:6380> 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 的文章您也可能喜欢,不妨参考下:

Ubuntu 14.04 下 Redis 安装及简单测试 http://www.linuxidc.com/Linux/2014-05/101544.htm

Redis 主从复制基本配置 http://www.linuxidc.com/Linux/2015-03/115610.htm

CentOS 7 下 Redis 的安装与配置 http://www.linuxidc.com/Linux/2017-02/140363.htm

Ubuntu 14.04 安装 Redis 与简单配置 http://www.linuxidc.com/Linux/2017-01/139075.htm

Ubuntu 16.04 环境中安装 PHP7.0 Redis 扩展 http://www.linuxidc.com/Linux/2016-09/135631.htm

Redis 单机 & 集群离线安装部署 http://www.linuxidc.com/Linux/2017-03/141403.htm

CentOS 7.0 安装 Redis 3.2.1 详细过程和使用常见问题 http://www.linuxidc.com/Linux/2016-09/135071.htm

Ubuntu 16.04 环境中安装 PHP7.0 Redis 扩展 http://www.linuxidc.com/Linux/2016-09/135631.htm

Ubuntu 15.10 下 Redis 集群部署文档 http://www.linuxidc.com/Linux/2016-06/132340.htm

Redis 实战 中文 PDF http://www.linuxidc.com/Linux/2016-04/129932.htm

Redis 热迁移实战总结  http://www.linuxidc.com/Linux/2017-02/141083.htm

Redis3.0 配置文件详解  http://www.linuxidc.com/Linux/2017-03/141369.htm

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-05/143433.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计6452字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中