Redis学习笔记(八): 哨兵模式

主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。

概述

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

作用

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

开启

Redis提供了redis-sentinel命令,后面跟配置文件即可.也可以使用redis-server /path/to/sentinel.conf --sentinel

配置

Redis提供了redis-sentinel命令,用来开启哨兵模式,不过单独的redis-sentinel命令只能使用代码中的默认配置,比如端口是26379,为了增加选举性,我们需要开启多个哨兵服务,这就涉及到使用指定配置文件来修改端口以及其他配置项了.

################### 基础配置 ###################
# 端口,默认26379
port 26379
# 是否以守护进程开启
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "/var/log/redis/redis-sentinel-26379.log"
dir "/var/soft/redis/data"
# 保护模式,默认关闭
protected-mode no
# 监控谁,设置主节点名称.最后一个参数是当几个哨兵认为主机失联后进行故障转移(重新选举master)
sentinel monitor mymaster 127.0.0.1 6379 2
# sentinel auth-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>

################### 其他配置 ###################
# 指定哨兵在监控Redis服务时,当Redis服务在一个默认毫秒数内都无法回答时,单个哨兵认为的主观下线时间,默认为30000(30秒)
sentinel down-after-milliseconds mymaster 30000
# 指定可以有多少个Redis服务同步新的主机,一般而言,这个数字越小同步时间越长,而越大,则对网络资源要求越高
sentinel parallel-syncs 2
# 指定故障切换允许的毫秒数,超过这个时间,就认为故障切换失败,默认为3分钟
sentinel failover-timeout mymaster 180000
# 指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,比较常用
sentinel notification-script mymaster shell_script_path 

sentinel down-after-milliseconds配置项只是一个哨兵在超过规定时间依旧没有得到响应后,会自己认为主机不可用。对于其他哨兵而言,并不是这样认为。哨兵会记录这个消息,当拥有认为主观下线的哨兵达到sentinel monitor所配置的数量时,就会发起一次投票,进行failover,此时哨兵会重写Redis的哨兵配置文件,以适应新场景的需要。

API

开启哨兵模式后,可以使用自带API查看各种状态

查看方式比较简单,使用redis-cli -p sentinel_port,这里列举一些简单命令,比较全的命令参考Redis sentinel API

# This command simply returns PONG.
PING 
SENTINEL masters 
# Show the state and info of the specified master.
SENTINEL master mymaster
# Show a list of replicas for this master, and their state.
SENTINEL slaves mymaster
# Show a list of sentinel instances for this master, and their state.
SENTINEL sentinels mymaster
# Return the ip and port number of the master with that name. If a failover is in progress or terminated successfully for this master it returns the address and port of the promoted replica.
SENTINEL get-master-addr-by-name mymaster

选举

只要有一个sentinel节点完成故障转移,就会涉及到选举.通过sentinel is-master-down-by-addr命令都希望成为领导者,过程如下:

1. 每个做主观下线的`sentinel`节点向其他`sentinel`节点发送命令,要求将它设置为领导者
2. 收到命令的`sentinel`节点如果没有同意通过其他`sentinel`节点发送的命令,那么将同意该请求,否则拒绝.
3. 如果该`sentinel`节点发现自己的票数已经超过`sentinel`集合半数且超过`quorum`(`conf中对于监控配置中的法定人数的设置 sentinel monitor master_name ip port quorum`)
4. 如果此过程有多个Sentinel节点成为了领导者,那么将等待一段时间重新进行选举.

Java客户端

Jedis测试

        JedisSentinelPool mymaster = new JedisSentinelPool("mymaster", Sets.newHashSet( "127.0.0.1:8379", "127.0.0.1:8380", "127.0.0.1:8381"));
        Jedis resource = mymaster.getResource();
        while (true) {
            TimeUnit.SECONDS.sleep(1);
            try {
                System.out.println(resource.get("hh"));
            } catch (Exception e) {
                System.out.println("getting...");
            }
        }

Springboot测试

yml

这里其实配置host没有实际作用,只不过利用了yml文件的特点,统一了取值.客户端会根据哨兵发送SENTINEL get-master-addr-by-name mymaster命令获取当前的主节点信息.

spring:
  #NoSQL缓存
  redis:
    database: 0
    host: ${REDIS_HOST:192.168.0.12}
    password: ${REDIS_PASSWORD:}
    port: ${REDIS_PORT:6379}
    timeout: 3000
    sentinel:
      master: mymaster
      nodes: ${spring.redis.host}:8379,${spring.redis.host}:8380,${spring.redis.host}:8381

RedisConfig

这里忽略其他配置,如序列化等等,可以参考spring boot集成redis的基本配置,只展示相关的RedisConnectionFactory类的配置,我使用LettuceConnectionFactory包裹自定义的RedisSentinelConfiguration来实现.

	@Autowired private RedisProperties redisProperties;

    @Bean
    @Primary
    public RedisSentinelConfiguration redisSentinelConfiguration() {
        RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
        sentinelConfiguration.setDatabase(redisProperties.getDatabase());
        RedisProperties.Sentinel sentinel = redisProperties.getSentinel(); sentinelConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        sentinelConfiguration.setMaster(sentinel.getMaster());
        List<String> nodes = sentinel.getNodes();
        List<RedisNode> collect = nodes.stream()
                .map(n -> {
                    String[] split = n.split(":");
                    return new RedisNode(split[0], Integer.parseInt(split[1]));
                })
                .collect(Collectors.toList());
        sentinelConfiguration.setSentinels(collect);
        return sentinelConfiguration;
    }

    @Bean
    @Primary
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisSentinelConfiguration());
    }

配置完成后, 简单的启动类测试代码:

@SpringBootApplication
public class IApplication implements ApplicationRunner {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public static void main(String[] args) {
        SpringApplication.run(IApplication.class, args);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String hello = stringRedisTemplate.opsForValue().get("hello");
        System.out.println(hello);
    }
}

问题

最好不要在哨兵配置文件里面填写127.0.0.1,如果不在服务器本机的话,客户端不认识.

参考

  1. Redis哨兵(Sentinel)模式
  2. Redis Sentinel Documentation
  3. Redis中文文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值