redis高级篇——redis哨兵

67 阅读3分钟

对于主从集群模式,如果从库发生了故障,还有主库和其它的从库可以接收请求,但是如果主库挂了,就不能进行正常的数据写入并且数据同步也不能正常的进行。要避免这种问题就需要使用Redis的哨兵机制。

什么是哨兵机制

哨兵(sentinel) 是一个分布式系统,哨兵节点是特殊的 Redis 服务,不提供读写,主要来监控 Redis 中的实例节点,当发现主节点异常时,会重新选出主节点,并通知其他节点去新的主节点进行数据同步。

于是,Redis哨兵机制有三个核心功能:监控,自动故障恢复,通知。

  • 监控:一般使用心跳机制通过不间断的发出 PING 命令,检测节点是否正常运行
  • 自动故障恢复:当有master发生故障,Sentinel会随机抽取一个slave提升为master。当故障实例恢复后也以新的master为主。
  • 通知:Sentinel充当Redis客户端的服务发现来源,当主节点发生故障并推选出新的master时,会将信息告知其他节点。

在实际场景中,Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  • 主观下线:如果有一个sentinel节点发现某实例未在规定时间内响应,则认为该实例主观下线。
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

选举新的master节点遵循的原则

  1. 判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则先排除该slave节点
  2. 判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  3. 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  4. 判断slave节点的运行id大小,id越小优先级越高

通过以上机制如果还存在几个同时满足条件的节点,则由Sentinel节点推选新的master节点。

推选出新的master节点之后,实现故障转移

  • sentinel给备选的slave节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 127.0.0.1 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • sentinel将故障的主节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

配置Sentinel

# 指定端口号
port 27001 
# 指定ip地址
sentinel announce-ip "127.0.0.1" 
# 指定主节点
sentinel monitor mymaster 127.0.0.1 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/home/redis-stable/sentinel/s1"

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

RedisTemplate的哨兵模式

  1. 引入依赖
<dependency>  
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId> 
</dependency>
  1. 在配置文件application.yml中指定sentinel的相关配置信息
spring:
  redis:
   sentinel:
     master: mymaster # 指定master名称
     nodes:  # 指定redis-sentinel集群信息 
     - 127.0.0.1:27001
     - 127.0.0.1:27002
  1. 配置主从读写分离
 @Bean
 public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
      return configBuilder -> configBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
       /*ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择:
       MASTER:从主节点读取
       MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
       REPLICA:从slave(replica)节点读取
       REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master*/
 }

总结

Redis的Sentinel机制仅仅解决了 高可用 的问题,对于 主节点 单点写入和单节点无法扩容等问题,还需要引入 Redis Cluster 集群模式 予以解决。

原作者:EtherealGoGoGo 本文复制自:juejin.cn/post/715168…