【Redis】哨兵模式

手动主从切换

主从复制/读写分离策略有个致命的问题,master挂掉且不可恢复了怎么办?

有一种方式是手动进行主从切换。具体的操作是,先在slave上执行slaveof no one命令把自己变成新的master,然后手动的把其他节点连接到这个新的master上。

显然,这种方式费时费力,还会造成一段时间内服务不可用。而哨兵模式,可以自动的、透明的、健壮的完成主从切换的任务。

 
 

原理讲解

哨兵是一个独立运行的的进程,它监控着所有的Redis服务器。

当然,一个哨兵可能还会出问题,因此可以设置多个哨兵,哨兵之间也能相互监控。

在这里插入图片描述

假设master宕机,哨兵x先检测到这个问题,但并不会立即进行failover(故障切换)操作,仅仅是哨兵x认为master不可用,称为主观下线;当其他的哨兵也发现master不可用,并且达到一定的数量时,那么便会通过投票选举出新的master,进行failover(故障切换)操作;切换成功后,新的master通过发布/订阅模式,通知其他slave修改配置,称为客观下线

 
 

相关配置

首先明确,redis-sentinel.confredis.conf是两个配置文件。

下面,我们来瞧瞧redis-sentinel.conf中究竟有哪些配置项吧 >_<!!!

# 哨兵实例运行的端口,默认为26379
port 26379


# 哨兵服务的临时工作文件夹,默认为/tmp,要保证有写入权限
dir /tmp


# 哨兵监控的主节点
# 后边紧跟的数字的含义是,有多少个哨兵认为主节点主观下线,则对其进行客观下线处理
sentinel monitor mymaster 127.0.0.1 6379 2


# redis开启密码服务后,所有连接redis服务器的客户端都要提供密码,哨兵也不例外
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd


# 指定多少毫秒之后,主节点未应答哨兵,则该哨兵认为其主观下线
sentinel down-after-milliseconds mymaster 30000


# 指定发生故障转移后,最多有多少个slave同时与新的master同步,类似于并行的数量限制
# 这个数字越小,则故障转移完成需要的时间越长;这个数字越大,对网络要求越高,并且意味着当前有多个slave不可用!
sentinel parallel-syncs mymaster 1


# 指定故障切换允许话费的最大毫秒数,超时则失败
sentinel failover-timeout mymaster 180000


# 指定某一事件发生后需要执行的脚本
# 比如,当系统运行不正常时,该脚本发送一个邮件通知相关人员
sentinel notification-script mymaster /var/redis/notify.sh


# 主节点切换后,该脚本将"主节点切换"的相关信息通知给客户端
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

 
 

Jedis原生写法

public class sentinelTest {

    @Test
    public void test() {
        // 连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(100);
        config.setMaxIdle(50);
        config.setMaxWaitMillis(2000);
        // 哨兵信息
        Set<String> sentinels = new HashSet<>(Arrays.asList("127.0.0.1.26379", "127.0.0.2.26379", "127.0.0.3.26379"));
        // 创建连接池
        JedisSentinelPool pool = new JedisSentinelPool("master", sentinels, config);
        // 获取客户端并使用
        Jedis jedis = pool.getResource();
        jedis.set("loli", "alice");
        System.out.println(jedis.get("loli"));
    }
}

 
 

Spring整合写法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 连接池配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100"/>
        <property name="maxIdle" value="50"/>
        <property name="maxWaitMillis" value="2000"/>
    </bean>

    <!-- 序列化器 -->
    <bean name="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    <bean name="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

    <!-- 哨兵配置 -->
    <bean name="sentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
        <!-- 主服务器 -->
        <property name="master">
            <bean class="org.springframework.data.redis.connection.RedisNode">
                <property name="name" value="master"/>
            </bean>
        </property>
        <!-- 哨兵IP与端口 -->
        <property name="sentinels">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="26379"/>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.2"/>
                    <constructor-arg name="port" value="26379"/>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.3"/>
                    <constructor-arg name="port" value="26379"/>
                </bean>
            </set>
        </property>
    </bean>

    <!-- 连接工厂 -->
    <bean name="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="sentinelConfig" ref="sentinelConfiguration"/>
        <constructor-arg name="poolConfig" ref="poolConfig"/>
    </bean>
    
    <!-- 模板类 -->
    <bean name="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="defaultSerializer" ref="jdkSerializationRedisSerializer"/>
        <property name="keySerializer" ref="stringRedisSerializer"/>
        <property name="valueSerializer" ref="stringRedisSerializer"/>
    </bean>


</beans>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

☘️ 玩转Redis专题!

🍄 不来博客里瞧一瞧吗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值