环境:192.168.1.25~27
Redis版本:redis-6.2.5
节点分部:一主二从三哨兵
数据节点实例: 192.168.1.25:5379, 192.168.1.26:5379, 192.168.1.27:5379
哨兵(sentinel)实例:192.168.1.25:25379, 192.168.1.26:25379, 192.168.1.27:25379
Redis-Sentinel官方文档:REDIS sentinel-old -- Redis中国用户组(CRUG)
2.1、redis安装
192.168.1.25~27
cd /home/asap/wbh/redis-6.2.5
make PREFIX=/home/asap/redis install
cp /home/asap/wbh/redis-6.2.5/redis.conf /home/asap/redis/5379/redis.conf
cp /home/asap/wbh/redis-6.2.5/sentinel.conf /home/asap/redis/25379/sentinel.conf
redis启停脚本
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
HOST=192.168.1.25
REDISPORT=5379
password=admin
HOME=/home/asap/redis
EXEC=${HOME}/bin/redis-server
CLIEXEC=${HOME}/bin/redis-cli
PIDFILE=${HOME}/redis_${REDISPORT}.pid
CONF="${HOME}/${REDISPORT}/redis.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -a $password -h $HOST -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
redis-sentinel启停脚本
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
HOST=192.168.1.25
REDISPORT=25379
password=admin
HOME=/home/asap/redis
EXEC=${HOME}/bin/redis-sentinel
CLIEXEC=${HOME}/bin/redis-cli
PIDFILE=${HOME}/redis-sentinel-${REDISPORT}.pid
CONF="${HOME}/${REDISPORT}/sentinel.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -h $HOST -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
将redis和redis-sentinel脚本拷贝到/home/asap/redis 并修改host
2.2、数据节点配置文件
master配置文件:redis.conf(192.168.1.25:5379)
port 5379
bind 192.168.1.25
requirepass "admin"
daemonize yes
logfile "/home/asap/redis/5379/5379.log"
dbfilename "dump-5379.rdb"
dir "/home/asap/redis/5379"
pidfile /home/asap/redis/redis_5379.pid
#如若master设置了认证密码,那么所有redis数据节点都配置上masterauth属性
masterauth "admin"
slave-1配置文件:redis.conf(192.168.1.26:5379)
port 5379
bind 192.168.1.26
requirepass "admin"
daemonize yes
logfile "/home/asap/redis/5379/5379.log"
dbfilename "dump-5379.rdb"
dir "/home/asap/redis/5379"
pidfile /home/asap/redis/redis_5379.pid
#如若master设置了认证密码,那么所有redis数据节点都配置上masterauth属性
masterauth "admin"
slaveof 192.168.1.25 5379
slave-2配置文件:redis.conf(192.168.1.27:5379)
port 5379
bind 192.168.1.27
requirepass "admin"
daemonize yes
logfile "/home/asap/redis/5379/5379.log"
dbfilename "dump-5379.rdb"
dir "/home/asap/redis/5379"
pidfile /home/asap/redis/redis_5379.pid
#如若master设置了认证密码,那么所有redis数据节点都配置上masterauth属性
masterauth "admin"
slaveof 192.168.1.25 5379
2.3、节点启动
192.168.1.25~27
cd /home/asap/redis
./redis start
./redis stop
3.1、3个sentinel节点的配置文件基本一致,区别的只是主机
192.168.1.25 sentinel.conf
bind 192.168.1.25
port 25379
daemonize yes
logfile "/home/asap/redis/25379/25379.log"
dir "/home/asap/redis/25379/"
pidfile /home/asap/redis/redis-sentinel-25379.pid
#sentinel monitor
#告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效。master-name只能包含英文字母,数字,和“.-_”这三个字符需要注意的是master-ip 要写真实的ip地址而不要用回环地址(127.0.0.1)。
sentinel monitor mymaster 192.168.1.25 5379 2
#redis数据master节点设置了认证,则需要如下配置
sentinel auth-pass mymaster admin
# sentinel down-after-milliseconds
#这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可#用的。 单位是毫秒,默认为30秒
sentinel down-after-milliseconds mymaster 30000
# sentinel parallel-syncs
#这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进#行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意
#味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel parallel-syncs mymaster 1
#sentinel failover-timeout
#failover-timeout 可以用在以下这些方面:
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间。
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
# 3.当想要取消一个正在进行的failover所需要的时间。
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
sentinel failover-timeout mymaster 180000
192.168.1.26 sentinel.conf
bind 192.168.1.27
port 25379
daemonize yes
logfile "/home/asap/redis/25379/25379.log"
dir "/home/asap/redis/25379/"
pidfile /home/asap/redis/redis-sentinel-25379.pid
#sentinel monitor
#告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效。master-name只能包含英文字母,数字,和“.-_”这三个字符需要注意的是master-ip 要写真实的ip地址而不要用回环地址(127.0.0.1)。
sentinel monitor mymaster 192.168.1.25 5379 2
#redis数据master节点设置了认证,则需要如下配置
sentinel auth-pass mymaster admin
# sentinel down-after-milliseconds
#这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可#用的。 单位是毫秒,默认为30秒
sentinel down-after-milliseconds mymaster 30000
# sentinel parallel-syncs
#这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进#行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意
#味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel parallel-syncs mymaster 1
#sentinel failover-timeout
#failover-timeout 可以用在以下这些方面:
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间。
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
# 3.当想要取消一个正在进行的failover所需要的时间。
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
sentinel failover-timeout mymaster 180000
192.168.1.27 sentinel.conf
bind 192.168.1.27
port 25379
daemonize yes
logfile "/home/asap/redis/25379/25379.log"
dir "/home/asap/redis/25379/"
pidfile /home/asap/redis/redis-sentinel-25379.pid
#sentinel monitor
#告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效。master-name只能包含英文字母,数字,和“.-_”这三个字符需要注意的是master-ip 要写真实的ip地址而不要用回环地址(127.0.0.1)。
sentinel monitor mymaster 192.168.1.25 5379 2
#redis数据master节点设置了认证,则需要如下配置
sentinel auth-pass mymaster admin
# sentinel down-after-milliseconds
#这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可#用的。 单位是毫秒,默认为30秒
sentinel down-after-milliseconds mymaster 30000
# sentinel parallel-syncs
#这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进#行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意
#味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel parallel-syncs mymaster 1
#sentinel failover-timeout
#failover-timeout 可以用在以下这些方面:
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间。
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
# 3.当想要取消一个正在进行的failover所需要的时间。
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
sentinel failover-timeout mymaster 180000
3.2、启动sentinel
192.168.1.25~27
cd /home/asap/redis
./ redis-sentinel start
./ redis-sentinel stop
redis-cli -h 192.168.1.26 -p 25379 -a admin
代码实现:
redis.clients
jedis
2.9.0
jar
compile
package com.asap.core;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.util.*;
/**
* Created by wbh
* On 2021/09/09.
*
* @description
*/
public class RedisService {
public static void main(String[] args) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(10);
poolConfig.setMaxTotal(50);
poolConfig.setMaxWaitMillis(60000);
poolConfig.setTestOnBorrow(true);
String password="admin";
//哨兵列表
Set sentinels = new HashSet();
sentinels.add("192.168.1.25:25379");
sentinels.add("192.168.1.26:25379");
sentinels.add("192.168.1.27:25379");
//在sentinel.conf配置的master-name
String clusterName = "mymaster";
JedisSentinelPool redisSentinelJedisPool = new JedisSentinelPool(clusterName, sentinels, poolConfig,password);
Jedis jedis = null;
while (true) {
try {
//活跃线程数
System.out.println("getNumActive:" + redisSentinelJedisPool.getNumActive());
//当前master信息
System.out.println("CurrentHostMaster:" + redisSentinelJedisPool.getCurrentHostMaster().toString());
jedis = redisSentinelJedisPool.getResource();
jedis.select(2);
String uuid = UUID.randomUUID().toString();
jedis.set(uuid, uuid);
jedis.expire(uuid, 500);
System.out.println(jedis.get(uuid));
Thread.sleep(1);
// break;
} catch (JedisConnectionException e) {
//master 挂了,重新获取master
System.out.println("try to connect master....");
continue;
} catch (Exception e) {
System.out.println("error...." + e);
break;
} finally {
try {
if (jedis != null) {
jedis.close();
}
} catch (Exception e) {
//忽略close异常
System.out.println("jedis.close() fail...");
}
}
}
redisSentinelJedisPool.close();
}
}