Skip to content

Redis-哨兵模式(sentinel)

1.是什么

使用redis主从服务会有一个问题,当主从服务宕机时,需要手动进行恢复,为了解决这个问题,redis增加了哨兵模式(因为哨兵模式可以监控主从服务器,并且提供自动容灾恢复的功能)。

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

image-20220822134936735

2.怎么玩

1.调整为一主二仆模式,6379主6380、6381从

image-20220822162230446

2.创建sentinel.conf文件

这创建redis6379.conf、redis6380.conf、redis6381.conf 是为了在本机模拟主从复制

image-20220822162716578

shell
#查看sentinel.conf文件,如果不存在则:wq保存进行创建
vi sentinel.conf
#查看sentinel.conf文件,如果不存在则:wq保存进行创建
vi sentinel.conf

sentinel.conf填写内容如下

shell
#mymaster为监控对象起的名称,
#127.0.0.1 6379 指定监听主机的ip和port
#1 表示至少有(1)几个哨兵同意迁移的数量
sentinel monitor mymaster 127.0.0.1 6379 1
#mymaster为监控对象起的名称,
#127.0.0.1 6379 指定监听主机的ip和port
#1 表示至少有(1)几个哨兵同意迁移的数量
sentinel monitor mymaster 127.0.0.1 6379 1

3.启动哨兵

shell
redis-sentinel /usr/local/src/myredis/sentinel.conf
redis-sentinel /usr/local/src/myredis/sentinel.conf

image-20220822163422423

4.当主机挂掉,从机选举中产生新的主机

1.我们将主机挂掉,发现大概10秒左右可以看到哨兵窗口日志,切换了新的主机

image-20220822163954697

2.当我们将挂掉的主机6379重启,可以看到6379变成了从机

image-20220822164640668

3.将现在的主机6380挂掉,6379又被切换成了主机

image-20220822170041421

5.复制延时

​ 由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

6.故障恢复,主机选举机制

image-20220822164155735

1.优先级在redis.conf中默认:slave-priority 100(老版本),在新版本中为replica-priority 100,值越小优先级越高

2.偏移量是指获得原主机数据最全的。比如在主机6379挂机之前,同步到6380有10个数据,而6381只有6个那么6380的偏移量就会更大也就会被选举为主机

3.每个redis实例启动后都会随机生成一个40位的runid,由于是随机的那么谁会成为主机也就不确定了

image-20220822165036660

7.jedis操作主从复制

java
public class JedisSentinel {
    private static JedisSentinelPool jedisSentinelPool = null;

    public static void main(String[] args) {
        Jedis jedis = getJedisFromSentinel();
        jedis.set("nickname", "孙悟空");
        String name = jedis.get("name");
        System.out.println(name);
        String nickname = jedis.get("nickname");
        System.out.println(nickname);
    }


    public static Jedis getJedisFromSentinel() {
        if (jedisSentinelPool == null) {
            Set<String> sentinelSet = new HashSet<>();
            sentinelSet.add("192.168.79.201:26379");
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(10); //最大可用连接数
            jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
            jedisPoolConfig.setMinIdle(5); //最小闲置连接数
            jedisPoolConfig.setBlockWhenExhausted(true); //连接耗尽是否等待
            jedisPoolConfig.setMaxWaitMillis(2000); //等待时间
            jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping pong
            jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig);
        }
        return jedisSentinelPool.getResource();
    }
}
public class JedisSentinel {
    private static JedisSentinelPool jedisSentinelPool = null;

    public static void main(String[] args) {
        Jedis jedis = getJedisFromSentinel();
        jedis.set("nickname", "孙悟空");
        String name = jedis.get("name");
        System.out.println(name);
        String nickname = jedis.get("nickname");
        System.out.println(nickname);
    }


    public static Jedis getJedisFromSentinel() {
        if (jedisSentinelPool == null) {
            Set<String> sentinelSet = new HashSet<>();
            sentinelSet.add("192.168.79.201:26379");
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(10); //最大可用连接数
            jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
            jedisPoolConfig.setMinIdle(5); //最小闲置连接数
            jedisPoolConfig.setBlockWhenExhausted(true); //连接耗尽是否等待
            jedisPoolConfig.setMaxWaitMillis(2000); //等待时间
            jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping pong
            jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig);
        }
        return jedisSentinelPool.getResource();
    }
}