搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

时间:2021-02-15 17:27:04

前言

某web项目中需要快速存取部分非结构化数据,对数据的安全性要求不高,同时由于web项目有多台服务器同时提供服务,并通过nginx负载均衡,需要保证客户端从任意一台服务器中均能读取到完整的数据。因此不能简单的在每台服务器中安装redis缓存,同时为避免单点故障,需要部署多台redis服务组成主从集群,而默认的主从配置仅仅保证了数据的复制与安全,并没有提供节点失败时的请求转移,因此需要配合redis-sentinel服务。

服务的安装与配置

Redis的安装

下载最新的redis.tar.gz包,解压后
./configure
make
make install
即可。
若需要tcl包的话,再另外编译安装就行。

Redis的主从配置

假设两台主机:192.168.0.1(主), 192.168.0.2(从)。则分别在两台主机安装redis后,编辑redis.conf 主服务器无需额外配置,从服务器增加
slaveof=192.168.0.1 6379
配置项,这样该从服务器上的redis会自动连接主服务器,并拷贝副本。

Sentinel的配置

当redis主从分配启动完成后,即可配置sentinel服务,编辑sentinel.conf文件,制定主服务器即可
sentinel monitor mymaster 192.168.0.1 6379 1
其中1代表投票的阈值,具体解释详见文档。

运行效果

实际运行例子中ip可能和上文不同,实例分别10.2.230.21和10.2.230.22

启动服务

主、从Redis服务启动

1、主服务器启动 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

2、从服务器启动 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

可以看到,从服务器自动从主服务器中同步了信息。 此时通过redis-cli查看info信息:redis-cli -h 'ip' info Replication 可以看到master服务中标明了slave的节点的数量,而从节点则标明了master的运行状态 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

Sentinel启动

此时启动sentinel服务 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]
从中可以看到master为10.2.230.21节点。

主从切换

1、手动关闭主节点
搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]
可以看到sentinel将master切换为了10.2.230.22,而从节点切换为10.2.230.21 info查看22节点的信息,可以看到输出也是主节点的信息,此时从节点连接数为0(21还未恢复服务)。 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

2、重新开启主节点
可以看到sentinel查找到了21的redis服务 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]
此时的info信息如下,可以看到21和22节点的主从身份已互换。 搭建Redis主从集群搭建、redis-sentinel的配置以及Jedis对Sentinel的使用[ by 嗡汤圆 ]

Java客户端Jedis代码编写

Jedis自带的JedisSentinelPool即可使用Sentinel架构下的Redis缓存服务。获取Jedis资源的代码如下: 第一步:建立连接池
Set<String> IPS = new HashMap<String>();
IPS.add("192.168.0.1:26379");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", IPS);
第二步:获取Jedis连接
Jedis jedis = pool.getResource();
第三步:使用Jedis缓存(在使用结束后记得关闭链接)
Jedis jedis=null;
try{
jedis = pool.getResource();
jedis.set("foo", "bar");
System.out.println(jedis.get("foo"));
} catch(Exception e){
logger.error(e);
} finally {
if(jedis != null)
jedis.close();
}

注意事项

新版本的redis中slave节点是只读的,因此对于缓存的读写操作不能仅仅通过pool.getResource()来获取Jedis实例进行读写,写操作需要保证自己连接的是master节点。由于不知道JedisSentinelPool有没有直接获取Master节点的功能,我目前的方法如下,通过直接指定ip和port进行连接,如果有更好的方法,欢迎各位回复。
public synchronized String set(String key, String value) throws Exception{
Jedis jedis = null;
try {
String hostIp = pool.getCurrentHostMaster().getHost();
int hostPort = pool.getCurrentHostMaster().getPort();
WifiLogUtil.wifiLogInfo("Jedis set", "Server >> ["+hostIp+":"+hostPort+"]");
jedis =new Jedis(hostIp, hostPort);
if(value == null)
return jedis.set(key, value);
return jedis.set(key, new String(value.getBytes(), "UTF-8"));
} catch (Exception e) {
WifiLogUtil.wifiLogError(e, "jedis set", "set jedis error : "+e);
throw e;
} finally {
if(jedis != null)
jedis.close();
}
}