当前位置: 首页 > news >正文

Redis哨兵模式(Sentinel)底层实现原理详细介绍

文章目录

  • 一、哨兵模式(Sentinel)的概念
  • 二、哨兵系统服务部署
    • 1. 参数配置
    • 2. 启动服务
    • 3. 检查状态
    • 4. 哨兵系统服务启动步骤
      • 4.1 初始化服务器
      • 4.2 使用Sentinel专用代码
      • 4.3 初始化Sentinel状态
      • 4.4 初始化Sentinel状态的masters属性
      • 4.5 创建连向主服务器的网络连接
  • 三、获取主从服务器信息
    • 1. 获取主服务器信息
    • 2. 获取从服务器信息
  • 四、与主从服务器的通信
    • 1. Sentinel向主从服务器发送信息
    • 2. Sentinel接收来自主从服务器的频道信息
  • 五、检测主服务器下线状态
    • 1. 检测主观下线状态
    • 2. 检测客观下线状态
  • 六、选举领头Sentinel机制
  • 七、故障转移
    • 1. 选出新的主服务器
    • 2. 修改从服务器的复制目标
    • 3. 将旧的主服务器变为从服务器
  • 总结

Redis哨兵模式(Sentinel)是Redis官方推荐的高可用解决方案,是在主从复制方案的基础上增加了自动监测、故障转移的功能,实现主节点故障后自动切换新的从节点作为主节点对外提供服务,保证系统高可用。以下是哨兵模式的详细介绍:

一、哨兵模式(Sentinel)的概念

Sentinel(哨岗、哨兵)是由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

在这里插入图片描述


二、哨兵系统服务部署

哨兵模式不仅需要部署主从服务节点,还需要配置并启动独立的哨兵系统服务节点进程,用来监听主服务器节点,提供哨兵系统功能服务。

1. 参数配置

主要通过复制Redis安装目录下的/home/redisadm/redis-6.2.14/sentinel.conf配置文件进行修改,以增加3个哨兵节点为例。/home/redisadm/redis-6.2.14/是我的Redis安装目录,/home/redisadm/redis-sentinel/是哨兵系统的配置目录。

假设主服务器节点端口为7001,从服务器节点端口为7002/7003/7004,3个哨兵节点的端口为27001/27002/27003。

  • 增加3个哨兵节点配置文件

    • /home/redisadm/redis-sentinel/27001/sentinel.conf
    • /home/redisadm/redis-sentinel/27002/sentinel.conf
    • /home/redisadm/redis-sentinel/27003/sentinel.conf
  • sentinel.conf文件主要配置:不同节点配置替换相应的端口信息就行

    # 主要配置参考,具体跟进自己的环境配置# 禁止保护模式
    protected-mode no# 端口
    port 27001// 让哨兵在后台运行
    daemonize yes# PID文件名
    pidfile /home/redisadm/redis-sentinel/27001/redis-sentinel.pid# 日志输出路径和文件名
    dir /home/redisadm/redis-sentinel/27001
    logfile "27001.log"// 当前Sentinel节点监控 127.0.0.1:7001 这个主节点
    // 2代表判断主节点失败至少需要2个Sentinel节点节点同意
    // mymaster是主节点的别名
    // sentinel monitor <master-name> <ip> <redis-port> <quorum>
    sentinel monitor mymaster 127.0.0.1 7001 2# 主服务器链接信息
    # sentinel auth-pass <master-name> <password>
    sentinel auth-pass mymaster 123456// 每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,
    // 如果超过30000毫秒30s且没有回复,则判定不可达
    sentinel down-after-milliseconds mymaster 30000// 当Sentinel节点集合对主节点故障判定达成一致时,
    // Sentinel领导者节点会做故障转移操作,选出新的主节点,
    // 原来的从节点会向新的主节点发起复制操作,
    // 限制每次向新的主节点发起复制操作的从节点个数为1
    sentinel parallel-syncs mymaster 1// 故障转移超时时间为180000毫秒
    sentinel failover-timeout mymaster 180000

2. 启动服务

执行启动命令,分别启动哨兵服务的3个节点。

# 保证sentinel的配置正确,否则,你在启动报错后,配置文件的内容会发生变化。
$ redis-sentinel /home/redisadm/redis-sentinel/27001/sentinel.conf 
$ redis-sentinel /home/redisadm/redis-sentinel/27002/sentinel.conf 
$ redis-sentinel /home/redisadm/redis-sentinel/27003/sentinel.conf 

或者

# 保证sentinel的配置正确,否则,你在启动报错后,配置文件的内容会发生变化。
$ redis-server /home/redisadm/redis-sentinel/27001/sentinel.conf --sentinel
$ redis-server /home/redisadm/redis-sentinel/27002/sentinel.conf --sentinel
$ redis-server /home/redisadm/redis-sentinel/27003/sentinel.conf --sentinel

3. 检查状态

启动好redis和哨兵节点后,执行检查命令查看哨兵节点状态。

redis-cli -p 27001 info sentinel
redis-cli -p 27002 info sentinel
redis-cli -p 27003 info sentinel

返回结果:

sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
# 看到最后一条信息正确即成功了哨兵,
# 哨兵主节点名字叫做mymaster,状态ok,
# 监控地址是127.0.0.0:7001,
# 有三个从节点,3个哨兵节点
master0:name=mymaster,status=ok,address=127.0.0.1:7001,slaves=3,sentinels=3

4. 哨兵系统服务启动步骤

Redis在使用命令启动哨兵节点服务器在Sentinel模式下运行时的步骤如下:

4.1 初始化服务器

因为Sentinel本质上只是一个运行在特殊模式下的Redis服务器,所以启动Sentinel的第一步,就是初始化一个普通的Redis服务器。

不过,因为Sentinel执行的工作和普通Redis服务器执行的工作不同,所以Sentinel的初始化过程和普通Redis服务器的初始化过程并不完全相同。比如Sentinel不会初始化以下功能:

  • 数据库和键值对方面的命令,比如SET、DEL、FLUSHDB等。
  • 事务命令,比如:MULTI、WATCH等。
  • 脚本命令,比如:EVAL等。
  • RDB和AOF持久化命令,比如:SAVE、BGSAVE、BGREWRITEAOF等。

4.2 使用Sentinel专用代码

将一部分普通Redis服务器使用的代码替换成Sentinel专用代码。普通Redis服务器使用redis.c/redisCommandTable作为服务器的命令表,而Sentinel则使用sentinel.c/sentinelcmds作为服务器的命令表,并且其中的INFO命令会使用Sentinel模式下的专用实现sentinel.c/sentinelInfoCommand函数,而不是普通Redis服务器使用的实现redis.c/infoCommand函数。

在Sentinel模式下,客户端只能对Sentinel执行如下七个命令:

struct redisCommand sentinelcmds[]={{"ping",pingCommand,1,"",0,NULL,0,0,0,0,0},{"sentinel",sentinelCommand,-2,"",0,NULL,0,0,0,0,0},{"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0},{"unsubscribe",unsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},{"psubscribe",psubscribeCommand,-2,"",0,NULL,0,0,0,0,0},{"punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},{"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}
};

4.3 初始化Sentinel状态

在应用了Sentinel的专用代码之后,接下来,服务器会初始化一个sentinel.c/sentinelState结构(后面简称“Sentinel状态”),这个结构保存了服务器中所有和Sentinel功能有关的状态(服务器的一般状态仍然由redis.h/redisServer结构保存):

struct sentinelState {
//当前纪元,用于实现故障转移
uint64_t current_epoch;
//保存了所有被这个sentinel,监视的主服务器
//字典的键是主服务器的名字
//字典的值则是一个指向sentinelRedisInstance结构的指针
dict *masters;
//是否进入了TILT模式?
int tilt;
//目前正在执行的脚本的数量
int running_scripts;
//进入TILT模式的时间
mstime_t tilt_start_time;
//最后一次执行时间处理器的时间
mstime_t previous_time;
//一个FIFO队列,包含了所有需要执行的用户脚本
list *scripts_queue;
} sentinel;

4.4 初始化Sentinel状态的masters属性

Sentinel状态中的masters字典记录了所有被Sentinel监视的主服务器的相关信息,其中:

  • 字典的键是被监视主服务器的名字。
  • 而字典的值则是被监视主服务器对应的sentinel.c/sentinelRedisInstance结构。

每个sentinelRedisInstance结构(后面简称“实例结构”)代表一个被Sentinel监视的Redis服务器实例(instance),这个实例可以是主服务器、从服务器,或者另外一个Sentinel。

typedef struct sentinelRedisInstance {int flags;                  // 实例类型及状态标识char *name;                 // 实例名称(IP:PORT 格式)char *runid;                // 运行 ID(Sentinel 或 Redis 实例唯一标识)uint64_t config_epoch;      // 配置纪元(故障转移时递增)sentinelAddr *addr;         // 网络地址信息,包含IP和PORTinstanceLink *link;         // 命令链接对象// 时间戳字段mstime_t last_pub_time;     // 最后一次发送 hello 消息时间mstime_t last_hello_time;   // 最后一次接收 hello 消息时间mstime_t s_down_since_time;// 主观下线时间mstime_t o_down_since_time;// 客观下线时间mstime_t down_after_period; // 主观下线判定超时时间// 主节点专用字段dict *sentinels;            // 监控同一主节点的 Sentinel 集合dict *slaves;               // 主节点的从节点集合unsigned int quorum;        // 客观下线所需投票数int parallel_syncs;         // 故障转移时同步从节点数量// 从节点专用字段mstime_t master_link_down_time; // 主从链接断开时间int slave_priority;         // 从节点优先级struct sentinelRedisInstance *master; // 指向主节点的指针// 故障转移相关char *leader;               // 故障转移领导者 Run IDmstime_t failover_start_time; // 故障转移开始时间mstime_t failover_timeout;  // 故障转移超时时间
} sentinelRedisInstance;

对Sentinel状态的初始化将引发对masters字典的初始化,而masters字典的初始化是根据被载入的Sentinel配置文件来进行的。
在这里插入图片描述

4.5 创建连向主服务器的网络连接

初始化Sentinel的最后一步是创建连向被监视主服务器的网络连接,Sentinel将成为主服务器的客户端,它可以向主服务器发送命令,并从命令回复中获取相关的信息。

对于每个被Sentinel监视的主服务器来说,Sentinel会创建两个连向主服务器的异步网络连接:

  • 一个是命令连接,这个连接专门用于向主服务器发送命令,并接收命令回复。
  • 另一个是订阅连接,这个连接专门用于订阅主服务器的__sentinel__:hello频道。
    • 在Redis目前的发布与订阅功能中,被发送的信息都不会保存在Redis服务器里面,如果在信息发送时,想要接收信息的客户端不在线或者断线,那么这个客户端就会丢失这条信息。因此,为了不丢失__sentinel__:hello频道的任何信息,Sentinel必须专门用一个订阅连接来接收该频道的信息。

在这里插入图片描述


三、获取主从服务器信息

1. 获取主服务器信息

Sentinel默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。

# Server
...
run_id:7611c59dc3a29aa6fa0609f841bb6a1019008a9c
...
# Replication
role:master
...
slave0:ip=127.0.0.1,port=7002,state=online,offset=43,lag=0
slave1:ip=127.0.0.1,port=7003,state=online,offset=43,lag=0
slave2:ip=127.0.0.1,port=7004,state=online,offset=43,lag=0
...
# Other sections
...

通过分析主服务器返回的INFO命令回复,Sentinel可以获取以下两方面的信息:

  • 一方面是关于主服务器本身的信息,包括run_id域记录的服务器运行ID,以及role域记录的服务器角色;
  • 另一方面是关于主服务器属下所有从服务器的信息,每个从服务器都由一个"slave"字符串开头的行记录,每行的ip=域记录了从服务器的IP地址,而port=域则记录了从服务器的端口号。根据这些IP地址和端口号,Sentinel无须用户提供从服务器的地址信息,就可以自动发现从服务器。

Sentinel根据run_id域和role域记录的信息,对主服务器的实例结构进行更新,至于主服务器返回的从服务器信息,则会被用于更新主服务器实例结构的slaves字典,如果slave存在则更新,如果slave不存在则新增。

在这里插入图片描述

2. 获取从服务器信息

当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构之外,Sentinel还会创建连接到从服务器的命令连接和订阅连接。

在创建命令连接之后,Sentinel在默认情况下,会以每十秒一次的频率通过命令连接向从服务器发送INFO命令,并获得类似于以下内容的回复:

# Server
...
run_id:32be0699dd27b410f7c90dada3a6fab17f97899f
...
# Replication
role:slave
master_host:127.0.0.1
master_port:7001
master_link_status:up
slave_repl_offset:11887
slave_priority:100
# Other sections
...

根据INFO命令的回复,Sentinel会提取出以下信息,根据这些信息,Sentinel会对从服务器的实例结构进行更新:

  • 从服务器的运行ID run_id。
  • 从服务器的角色role。
  • 主服务器的IP地址master_host,以及主服务器的端口号master_port。
  • 主从服务器的连接状态master_link_status。
  • 从服务器的优先级slave_priority。
  • 从服务器的复制偏移量slave_repl_offset。

四、与主从服务器的通信

Sentinel对__sentinel__:hello频道的订阅会一直持续到Sentinel与服务器的连接断开为止。对于每个与Sentinel连接的服务器,Sentinel既通过命令连接向服务器的__sentinel__:hello频道发送信息,又通过订阅连接从服务器的__sentinel__:hello频道接收信息。

1. Sentinel向主从服务器发送信息

在默认情况下,Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:

PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

这条命令向服务器的__sentinel__:hello频道发送了一条信息,信息的内容由多个参数组成:

  • 以s_开头的参数记录的是Sentinel本身的信息:
    • s_ip:发送方 Sentinel 的 IP 地址。
    • s_port:发送方 Sentinel 的端口。
    • s_runid:发送方 Sentinel 的运行 ID。
    • s_epoch:发送方 Sentinel 的配置纪元(config_epoch
  • 以m_开头的参数记录的则是被监视服务器的信息(如果是监控的主服务器则是主服务器的信息,反之如果监控的是从服务器则是从服务器信息):
    • m_name:被监控主节点的逻辑名称。
    • m_ip:被监控主节点的 IP 地址。
    • m_port:被监控主节点的端口。
    • m_epoch:被监控主节点的配置纪元(config_epoch)。

2. Sentinel接收来自主从服务器的频道信息

当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:

SUBSCRIBE __sentinel__:hello

对于监视同一个服务器的多个Sentinel来说,一个Sentinel发送的信息会被其他Sentinel接收到,这些信息会被用于更新其他Sentinel对发送信息Sentinel的认知,也会被用于更新其他Sentinel对被监视服务器的认知。

当一个Sentinel从__sentinel__:hello频道收到一条信息时,Sentinel会对这条信息进行分析,提取出信息中的Sentinel IP地址、Sentinel端口号、Sentinel运行ID等八个参数,并进行以下检查:

  • 如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID相同,那么说明这条信息是Sentinel自己发送的,Sentinel将丢弃这条信息,不做进一步处理。
  • 如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID不相同,那么说明这条信息是监视同一个服务器的其他Sentinel发来的,接收信息的Sentinel将根据信息中的各个参数,对相应主服务器的实例结构进行更新。
    • 更新sentinels字典:Sentinel为主服务器创建的实例结构中的sentinels字典保存了除Sentinel本身之外,所有同样监视这个主服务器的其他Sentinel的信息。
    • 创建连向其他Sentinel的命令连接:当Sentinel通过频道信息发现一个新的Sentinel时,它不仅会为新Sentinel在sentinels字典中创建相应的实例结构,还会创建一个连向新Sentinel的命令连接,而新Sentinel也同样会创建连向这个Sentinel的命令连接,最终监视同一主服务器的多个Sentinel将形成相互连接的网络。

五、检测主服务器下线状态

1. 检测主观下线状态

  • 在默认情况下,Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他Sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。实例对PING命令的回复可以分为以下两种情况:

    • 有效回复:实例返回+PONG、-LOADING、-MASTERDOWN三种回复的其中一种。
    • 无效回复:实例返回除+PONG、-LOADING、-MASTERDOWN三种回复之外的其他回复,或者在指定时限内没有返回任何回复。
  • Sentinel配置文件中的down-after-milliseconds选项指定了Sentinel判断实例进入主观下线所需的时间长度:如果一个实例在down-after-milliseconds毫秒内,连续向Sentinel返回无效回复,那么Sentinel会修改这个实例所对应的实例结构,在结构的flags属性中打开SRI_S_DOWN标识,以此来表示这个实例已经进入主观下线状态。

  • 用户设置的down-after-milliseconds选项的值,不仅会被Sentinel用来判断主服务器的主观下线状态,还会被用于判断主服务器属下的所有从服务器,以及所有同样监视这个主服务器的其他Sentinel的主观下线状态。

  • Sentinel配置文件中的down-after-milliseconds选项另一个需要注意的地方是,对于监视同一个主服务器的多个Sentinel来说,这些Sentinel所设置的down-after-milliseconds选项的值也可能不同,因此,当一个Sentinel将主服务器判断为主观下线时,其他Sentinel可能仍然会认为主服务器处于在线状态。

2. 检测客观下线状态

当Sentinel将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线了,它会向同样监视这一主服务器的其他Sentinel进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。当Sentinel从其他Sentinel那里接收到足够数量的已下线判断之后,Sentinel就会将从服务器判定为客观下线,并对主服务器执行故障转移操作。

  • (1)发送SENTINEL is-master-down-by-addr命令:询问其他Sentinel是否同意主服务器已下线。

    SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
    
  • (2)接收SENTINEL is-master-down-by-addr命令:当一个Sentinel(目标Sentinel)接收到另一个Sentinel(源Sentinel)发来的SENTINEL is-master-down-by命令时,目标Sentinel会分析并取出命令请求中包含的各个参数,并根据其中的主服务器IP和端口号,检查主服务器是否已下线,然后向源Sentinel返回一条包含三个参数的MultiBulk回复:

    • down_state0-表示主服务器未客观下线,1-表示主服务器已客观下线。
    • leader_runid*-表示检测主服务器下线状态,runid-如果是Sentinel运行ID则表示正在进行选举领头Sentinel。
    • leader_epoch:如果leader_runid为*时,始终为0,只有当leader_runid不为*时,存放的是领头选举时领头Sentinel的配置纪元。
  • (3)接收SENTINEL is-master-down-by-addr命令的回复:根据其他Sentinel发回的SENTINEL is-master-down-by-addr命令回复,Sentinel将统计其他Sentinel同意主服务器已下线的数量,当这个下线数量大于等于Sentinel配置中设置的quorum参数的值,Sentinel会将主服务器实例结构flags属性的SRI_O_DOWN标识打开,表示主服务器已经进入客观下线状态。

    • 不同Sentinel判断主服务器客观下线的条件可以不一样,需要达到Sentinel配置的quorum参数大小。

六、选举领头Sentinel机制

Redis 集群使用 Raft 算法来实现领导者选举,确保集群的稳定性和一致性。

当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个Sentinel会进行协商,选举出一个领头Sentinel,并由领头Sentinel对下线主服务器执行故障转移操作。

以下是Redis选举领头Sentinel的详细步骤方法:

  1. 所有在线的Sentinel都有被选为领头Sentinel的资格,换句话说,监视同一个主服务器的多个在线Sentinel中的任意一个都有可能成为领头Sentinel。
  2. 每次进行领头Sentinel选举之后,不论选举是否成功,所有Sentinel 的配置纪元(configuration epoch)的值都会自增一次。配置纪元实际上就是一个计数器,并没有什么特别的。
  3. 在一个配置纪元里面,所有Sentinel都有一次将某个Sentinel设置为局部领头Sentinel的机会,并且局部领头一旦设置,在这个配置纪元里面就不能再更改。
  4. 每个发现主服务器进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部领头Sentinel。
  5. 当一个Sentinel(源Sentinel)向另一个Sentinel(目标Sentinel)发送SENTINELis-master-down-by-addr命令,并且命令中的runid参数不是*符号而是源Sentinel的运行ID时,这表示源Sentinel要求目标Sentinel将前者设置为后者的局部领头Sentinel。
  6. Sentinel设置局部领头Sentinel的规则是先到先得:最先向目标Sentinel发送设置要求的源Sentinel将成为目标Sentinel的局部领头Sentinel,而之后接收到的所有设置要求都会被目标Sentinel拒绝。
  7. 目标Sentinel在接收到SENTINEL is-master-down-by-addr命令之后,将向源Sentinel返回一条命令回复,回复中的leader_runid参数和leader_epoch参数分别记录了目标Sentinel的局部领头Sentinel的运行ID和配置纪元。
  8. 源Sentinel在接收到目标Sentinel返回的命令回复之后,会检查回复中leader_epoch参数的值和自己的配置纪元是否相同,如果相同的话,那么源Sentinel继续取出回复中的leader_runid参数,如果leader_runid参数的值和源Sentinel的运行ID一致,那么表示目标Sentinel将源Sentinel设置成了局部领头Sentinel。
  9. 如果有某个Sentinel被半数以上的Sentinel设置成了局部领头Sentinel,那么这个Sentinel成为领头Sentinel。比如:在一个由10个Sentinel组成的Sentinel系统里面,只要有大于等于10/2+1=6个Sentinel将某个Sentinel设置为局部领头Sentinel,那么被设置的那个Sentinel就会成为领头Sentinel。
  10. 因为领头Sentinel的产生需要半数以上Sentinel的支持,并且每个Sentinel在每个配置纪元里面只能设置一次局部领头Sentinel,所以在一个配置纪元里面,只会出现一个领头Sentinel。
  11. 如果在给定时限内,没有一个Sentinel被选举为领头Sentinel,那么各个Sentinel将在一段时间之后再次进行选举,直到选出领头Sentinel为止。
  12. 最终胜出领头Sentinel的选举,这个领头Sentinel就可以开始对主服务器执行故障转移操作了。

七、故障转移

在选举产生出领头Sentinel之后,领头Sentinel将对已下线的主服务器执行故障转移操作,该操作包含以下三个步骤:

1. 选出新的主服务器

故障转移操作第一步要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好、数据完整的从服务器,然后向这个从服务器发送SLAVEOF no one命令,将这个从服务器转换为主服务器。

# 断开复制,晋升为主服务器
SLAVEOF no one

领头Sentinel会将已下线主服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:

  • (1)删除列表中所有处于下线或者断线状态的从服务器,这可以保证列表中剩余的从服务器都是正常在线的。
  • (2)删除列表中所有最近五秒内没有回复过领头Sentinel的INFO命令的从服务器,这可以保证列表中剩余的从服务器都是最近成功进行过通信的。
  • (3)删除所有与已下线主服务器连接断开超过down-after-milliseconds*10毫秒的从服务器:down-after-milliseconds选项指定了判断主服务器下线所需的时间,而删除断开时长超过down-after-milliseconds*10毫秒的从服务器,则可以保证列表中剩余的从服务器都没有过早地与主服务器断开连接,换句话说,列表中剩余的从服务器保存的数据都是比较新的。

首先,领头Sentinel将根据从服务器的优先级(配置参数replica-priority),对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器。

然后,如果有多个具有相同最高优先级的从服务器,那么领头Sentinel将按照从服务器的复制偏移量(配置参数replication offset),对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器(复制偏移量最大的从服务器就是保存着最新数据的从服务器)。

最后,如果有多个优先级最高、复制偏移量最大的从服务器,那么领头Sentinel将按照运行ID对这些从服务器进行排序,并选出其中运行ID最小的从服务器。

2. 修改从服务器的复制目标

当新的主服务器出现之后,领头Sentinel下一步要做的就是,让已下线主服务器属下的所有从服务器去复制新的主服务器,这一动作可以通过向从服务器发送SLAVEOF命令来实现。

# 建立或切换主节点
SLAVEOF <master_ip> <master_port>  

3. 将旧的主服务器变为从服务器

故障转移操作最后要做的是,将已下线的主服务器设置为新的主服务器的从服务器。

因为旧的主服务器已经下线,所以这种设置是保存在原已下线的主服务器对应的实例结构里面的,当原已下线的主服务器重新上线时,Sentinel就会向它发送SLAVEOF命令,让它成为当前主服务器的从服务器。


总结

Redis哨兵模式(Sentinel)通过部署多个Sentinel节点来监测主服务器状态,当发现主服务器客观下线时,主动发起领头Sentinel选举,基于 Raft 算法,选举完成后新的领头Sentinel会对以下线的主服务器进行故障转移,选出一个优先级最高的从服务器作为新的主服务器对外提供服务及更新主从复制同步关系,旧的主服务器在重启后变为当前新的主服务器的从服务器。

http://www.dtcms.com/a/295917.html

相关文章:

  • Python函数式编程之美:深入理解生成器与高阶函数
  • Product Hunt 每日热榜 | 2025-07-24
  • Java技术栈/面试题合集(17)-Git篇
  • 排序查找算法,Map集合,集合的嵌套,Collections工具类
  • Django实时通信实战:WebSocket与ASGI全解析(上)
  • LAYOUT 什么时候需要等长布线?
  • CodeBuddy IDE发布:编程新时代的颠覆者?
  • Transformer Masked loss原理精讲及其PyTorch逐行实现
  • 【Spring Cloud Gateway 实战系列】高级篇:服务网格集成、安全增强与全链路压测
  • 在 Alpine Linux 中创建虚拟机时 Cgroup 挂在失败的现象
  • spring/springboot SPI(二)配合使用的接口
  • 用 AI 破解数据质量难题:从缺失值填补到动态监控的高效解决方案
  • 数据所有权与用益权分离:数字经济时代的权利博弈与“商业机遇”
  • element-plus 组件 ElMessage、ElLoading 弹框 和加载css 样式展示异常总结
  • 【数学,放缩,基本不等式】基本不等式题目
  • TDengine 转化类函数 CAST 用户手册
  • SpringBoot复习
  • Flink-1.19.0源码详解8-ExecutionGraph生成-前篇
  • 洛谷刷题7.24
  • CellFlow:Flow matching建模cell状态变化
  • 如何将拥有的域名自定义链接到我的世界服务器(Minecraft服务器)
  • 大数据集分页优化:LIMIT OFFSET的替代方案
  • Oracle国产化替代:一线DBA的技术决策突围战
  • 如何判断钱包的合约签名是否安全?
  • MySQL深度理解-MySQL索引优化
  • 数据库第一章练习题(大雪圣期末参考复习)
  • 【数据结构】二叉树进阶算法题
  • MinIO 版本管理实践指南(附完整 Go 示例)
  • 一次粗心导致的bug定位
  • 《C++ string 完全指南:string的模拟实现》