Redis高级功能

news2025/1/24 11:44:36

目录

1.RDB 持久化

1.1生成RDB文件的命令

1.2RDB 文件结构

1.3RDB 文件结构 - database 部分

2.AOF 持久化

2.主从复制

2.1重同步 - 完整重同步 

2.2重同步 - 部分重同步

2.2.1重同步 - 部分重同步的实现 - PSYNC的实现原理 

3.复制的具体过程

3.Sentinel 哨兵模式

3.1启动并初始化Sentinel

3.2 获取主服务器信息

3.3获取从服务器信息

3.4 向主服务器和从服务器发送信息

3.5 接收来自主服务器和从服务器的频道信息 

3.6 接收来自主服务器和从服务器的频道信息 

3.7检测主、客观下线状态

3.8选举领头Sentinel 

3.9故障转移


1.RDB 持久化

  • Redis是内存数据库,它将自己的数据库状态储存在内存里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。 为了解决这个问题,Redis提供了RDB持久化功能,这个功能可以将Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。
  • RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。和使用SAVE命令或者BGSAVE命令创建RDB文件不同,RDB文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件存在,它就会自动载入RDB文件。因为RDB文件是保存在硬盘里面的,所以即使Redis服务器进程退出,甚至运行Redis服务器的计算机停机,但只要RDB文件仍然存在,Redis服务器就可以用它来还原数据库状态。

1.1生成RDB文件的命令

有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE

SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求(SAVE命令,大家只有在测试、开发环境手动使用就行了);和SAVE命令直接阻塞服务器进程的做法不同,BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求(redis的主从复制的时候)。

BGSAVE命令的保存工作是由子进程执行的,所以在子进程创建RDB文件的过程中,Redis服务器仍然可以继续处理客户端的命令请求,但是,在BGSAVE命令执行期间,服务器处理SAVE、BGSAVE、BGREWRITEAOF三个命令的方式会和平时有所不同。

首先,在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝,防止产生竞争条件。 其次,在BGSAVE命令执行期间,客户端发送的BGSAVE命令会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竞争条件。

最后,出于性能方面的考虑,BGREWRITEAOF和BGSAVE两个命令不能同时执行: ·如果BGSAVE命令正在执行,那么客户端发送的BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行(BGSVAE 不排斥BGREWRITEAOF,排队效应)。 ·如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。

1.2RDB 文件结构

下图展示了一个完整RDB文件所包含的各个部分:

  •  RDB文件的最开头是REDIS部分,这个部分的长度为5字节,保存着“REDIS”五个字符。通过这五个字符,程序可以在载入文件时,快速检查所载入的文件是否RDB文件。
  • db_version长度为4字节,它的值是一个字符串表示的整数,这个整数记录了RDB文件的版本号,比如"0006"就代表RDB文件的版本为第六版。
  • databases部分包含着零个或任意多个数据库,以及各个数据库中的键值对数据。如果服务器的数据库状态为空),那么这个部分也为空,长度为0字节。
  • EOF常量的长度为1字节,这个常量标志着RDB文件正文内容的结束。
  • check_sum是一个8字节长的无符号整数,保存着一个校验和,这个校验和是程序通过对REDIS、db_version、databases、EOF四个部分的内容进行计算得出的。服务器在载入RDB文件时,会将载入数据所计算出的校验和与check_sum所记录的校验和进行对比,以此来检查RDB文件是否有出错或者损坏的情况出现。

1.3RDB 文件结构 - database 部分

每个非空数据库在RDB文件中都可以保存为SELECTDB、db_number、key_value_pairs三个部分:

  1. SELECTDB常量的长度为1字节,当读入程序遇到这个值的时候,它知道接下来要读入的将是一个数据库号码。
  2. db_number保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是1字节、2字节或者5字节。当程序读入db_number部分之后,服务器会调用SELECT命令,根据读入的数据库号码进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中。
  3. key_value_pairs部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。根据键值对的数量、类型、内容以及是否有过期时间等条件的不同,key_value_pairs部分的长度也会有所不同。 

2.AOF 持久化

除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。

AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤

命令追加:当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾:

struct redisServer {
    // ...
    // AOF缓冲区
    sds aof_buf;
    // ...
};

写入与同步

服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数进行文件写入。flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定,各个不同值产生的行为如表

如果用户没有主动为appendfsync选项设置值,那么appendfsync选项的默认值为everysec。服务器配置appendfsync选项的值直接决定AOF持久化功能的效率和安全性。

  • 当appendfsync的值为always时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,所以always的效率是最慢的;但always也是最安全的,因为即使出现故障,只会丢失一个事件循环中所产生的命令数据。(并发量不高,并且对数据要求百分百(redis保证99%,剩余的1%由我们的程序保证,每进行一个redis操作,从程序层面也要进行一次记录)不丢失的情况下,用 always)
  • 当appendfsync的值为everysec时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行一次同步。everysec模式足够快,并且就算出现故障停机,也只丢失一秒钟的命令数据。
  • 当appendfsync的值为no时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,至于何时对AOF文件进行同步,则由操作系统控制。

2.主从复制

  • 在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave)。
  • 当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态。

Redis的复制功能分为同步(sync)和命令传播(command propagate)两个操作:

  1.  同步。是第一次进行主从服务器连接的时候,一定会进行同步操作(主服务器-RDB文件传输-从服务器);从服务器断线重连主服务器的时候,有可能触发同步操作(如果从服务器短线期间,新的命令都存在主服务器的缓冲区里,那么就直接发送这部分命令(命令传播)给从服务器就可以了;如果这些新的命令,不全部存在于主服务器的缓冲区中,则触发同步操作(RDB 文件))。
  2.  命令传播。第一次链接完我们的主服务器后,通过RDB文件同步之后的所有的命令,都是采用命令传播的形式。 同理,断线重连之后的所有主从数据的同步都采用命令传播。

2.1重同步 - 完整重同步 

RDB文件同步(1. 第一次连接;2 断线重连有可能触发RDB文件同步)

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式:

其中完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。(如下图为完整重同步)

完整重同步,需要主服务器生成一个新的 RDB文件,文件生成的开销是有得; RDB文件是整个的redis的数据状态,整个状态的 RDB文件体积不会太小,传输给从服务器需要网络开销及时间; 相比于小体积的命令传播,这个RDB 文件开销大得多。

2.2重同步 - 部分重同步

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式:

部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送(命令传播)给从服务器(缓冲区大小是否能够容纳断线期间的命令),从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。

部分重同步过程

  1. 主服务器和从服务器都需要记录一个偏移量,比如从服务器断线时,偏移量是100;断线期间主服务器从100 变为了120, 那么这20的偏移量就是需要进行同步的;
  2. 断线期间的命令必须有一个地方放;
  3. 主服务器有多个从服务器,每个从服务器都需要维护自己的偏移量,主服务器如果想要区分每个服务器的偏移量,需要通过一个唯一的id标识从服务器

2.2.1重同步 - 部分重同步的实现 - PSYNC的实现原理 

  • PSYNC命令的调用方法有两种: ·如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步)。 ·相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC <runid> <offset>命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的复制偏移量,接收到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行哪种同步操作。
  • 根据情况,接收到PSYNC命令的主服务器会向从服务器返回以下三种回复的其中一种: ·如果主服务器返回+FULLRESYNC <runid> <offset>回复,那么表示主服务器将与从服务器执行完整重同步操作:其中runid是这个主服务器的运行ID,从服务器会将这个ID保存起来,在下一次发送PSYNC命令时使用;而offset则是主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量。
  • 如果主服务器返回+CONTINUE回复,那么表示主服务器将与从服务器执行部分重同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了。
  • 如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8(SYNC: SYNC 没有部分重同步),它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并与主服务器执行完整同步操作。

3.复制的具体过程

  • 设置主服务器的地址和端口:当客户端向从服务器发送以下命令时:SLAVEOF 127.0.0.1 6379。 从服务器首先要做的就是将客户端给定的主服务器IP地址127.0.0.1以及端口6379保存到服务器状态的masterhost属性和masterport属性里面。SLAVEOF命令是一个异步命令,在完成masterhost属性和masterport属性的设置工作之后,从服务器将向发送SLAVEOF命令的客户端返回OK,表示复制指令已经被接收,而实际的复制工作将在OK返回之后才真正开始执行
  • 建立套接字连接 在SLAVEOF命令执行之后,从服务器将根据命令所设置的IP地址和端口,创建连向主服务器的套接字连接,从服务器可以向主服务器发送命令请求,而主服务器则会向从服务器返回命令回复
  • 发送PING命令:从服务器成为主服务器的客户端之后,做的第一件事就是向主服务器发送一个PING命令。这个PING命令有两个作用: ·通过发送PING命令可以检查套接字的读写状态是否正常。 ·通过发送PING命令可以检查主服务器能否正常处理命令请求。 从服务器在发送PING命令之后将遇到以下三种情况的其中一种: ·如果服务器不能在规定的时限(timeout)内读取出命令回复的内容,那么表示主从服务器之间的网络连接状态不佳,不能继续执行复制工作的后续步骤。当出现这种情况时,从服务器断开并重新创建连向主服务器的套接字。 ·如果主服务器向从服务器返回一个错误,那么表示主服务器暂时没办法处理从服务器的命令请求,不能继续执行复制工作的后续步骤。当出现这种情况时,从服务器断开并重新创建连向主服务器的套接字 ·如果从服务器读取到"PONG"回复,那么表示主从服务器之间的网络连接状态正常,并且主服务器可以正常处理从服务器(客户端)发送的命令请求,在这种情况下,从服务器可以继续执行复制工作的下个步骤。
  • 身份验证 从服务器在收到主服务器返回的"PONG"回复之后,下一步要做的就是决定是否进行身份验证:
  • 如果从服务器设置了masterauth选项,那么进行身份验证。
  • 如果从服务器没有设置masterauth选项,那么不进行身份验证。 从服务器在身份验证阶段可能遇到的情况有以下几种:
  • 如果主服务器没有设置requirepass选项,并且从服务器也没有设置masterauth选项,那么主服务器将继续执行从服务器发送的命令,复制工作可以继续进行。
  • 如果从服务器通过AUTH命令发送的密码和主服务器requirepass选项所设置的密码相同,那么主服务器将继续执行从服务器发送的命令,复制工作可以继续进行。与此相反,如果主从服务器设置的密码不相同,那么主服务器将返回一个invalid password错误。
  • 如果主服务器设置了requirepass选项,但从服务器却没有设置masterauth选项,那么主服务器将返回一个NOAUTH错误。另一方面,如果主服务器没有设置requirepass选项,但从服务器却设置了masterauth选项,那么主服务器将返回一个no password is set错误。
  •  发送端口信息 在身份验证步骤之后,从服务器将执行命令REPLCONF listening-port <port-number>,向主服务器发送从服务器的监听端口号 主服务器在接收到这个命令之后,会将端口号记录在从服务器所对应的客户端状态的slave_listening_port属性中
  • 同步 在这一步,从服务器将向主服务器发送PSYNC命令,执行同步操作,并将自己的数据库更新至主服务器数据库当前所处的状态。 值得一提的是,在同步操作执行之前,只有从服务器是主服务器的客户端,但是在执行同步操作之后,主服务器也会成为从服务器的客户端: ·如果PSYNC命令执行的是完整重同步操作,那么主服务器需要成为从服务器的客户端,才能将保存在缓冲区里面的写命令发送给从服务器执行。 ·如果PSYNC命令执行的是部分重同步操作,那么主服务器需要成为从服务器的客户端,才能向从服务器发送保存在复制积压缓冲区里面的写命令。

3.Sentinel 哨兵模式

  • Sentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
  • 假设这时,主服务器server1进入下线状态,那么从服务器server2、server3、server4对主服务器的复制操作将被中止,并且Sentinel系统会察觉到server1已下线。 首先,Sentinel系统会挑选server1属下的其中一个从服务器,并将这个被选中的从服务器升级为新的主服务器。 ·之后,Sentinel系统会向server1属下的所有从服务器发送新的复制指令,让它们成为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕。 ·另外,Sentinel还会继续监视已下线的server1,并在它重新上线时,将它设置为新的主服务器的从服务器。

整体流程:

  1.  如果主服务器进行了断开,替换了从服务器。除了被提升为主服务器的从服务器。所有的从服务器都必须做一次完整重同步(服务器的运行ID发生了变化,进行完整重同步)。原来的主服务器,上线之后,无论作为谁的从服务器,都必须进行一次完整重同步。 提升为新的主服务的压力在于 BGSAVE(几乎进行一次即可), 但是需要进行多份的网络传递; 第二次BGSAVE应该发生在 “新的” 从服务器链接到主服务器。 主服务器断链,是一件很可怕的事情。会造成服务短时间不可用(还没选举出新的主服务器的时候),再次造成服务的卡顿(BGSAVE 和 rdb文件多份传输的时候)。
  2. 集群,多个主,这个主服务器只是一个集群里的节点。如果这个节点挂了,那我们的集群就会将请求路由到其他的主服务器节点上,上边说的这个压力,在集群环境下就微乎其服务器微了。
  3. 如果是从服务器下线了,就是之前所说的断线重连 pysnc那部分内容。

3.1启动并初始化Sentinel

启动一个Sentinel可以使用命令:

$ redis-sentinel /path/to/your/sentinel.conf

或者命令: $ redis-server /path/to/your/sentinel.conf --sentinel

这两个命令的效果完全相同。 当一个Sentinel启动时,它需要执行以下步骤:

  1. 初始化服务器。 因为Sentinel执行的工作和普通Redis服务器执行的工作不同,所以Sentinel的初始化过程和普通Redis服务器的初始化过程并不完全相同。普通服务器在初始化时会通过载入RDB文件或者AOF文件来还原数据库状态,但是因为Sentinel并不使用数据库,所以初始化Sentinel时就不会载入RDB文件或者AOF文件。
  2. 将普通Redis服务器使用的代码替换成Sentinel专用代码。 启动Sentinel的第二个步骤就是将一部分普通Redis服务器使用的代码替换成Sentinel专用代码。比如说,普通Redis服务器使用redis.h/REDIS_SERVERPORT常量的值作为服务器端口: #define REDIS_SERVERPORT 6379 而Sentinel则使用sentinel.c/REDIS_SENTINEL_PORT常量的值作为服务器端口: #define REDIS_SENTINEL_PORT 26379 除此之外,普通Redis服务器使用redis.c/redisCommandTable作为服务器的命令表,而Sentinel则使用sentinel.c/sentinelcmds作为服务器的命令表
  3. 初始化Sentinel状态。 在应用了Sentinel的专用代码之后,接下来,服务器会初始化一个sentinel.c/sentinelState结构(后面简称“Sentinel状态”),这个结构保存了服务器中所有和Sentinel功能有关的状态。
struct sentinelState {
    // 当前纪元,用于实现故障转移
    uint64_t current_epoch;
    // 保存了所有被这个sentinel监视的主服务器
    dict *masters;
    // 是否进入了TILT模式?
    int tilt;
    // 目前正在执行的脚本的数量
    int running_scripts;
    // 进入TILT模式的时间
  mstime_t tilt_start_time;
    // 最后一次执行时间处理器的时间
    mstime_t previous_time;
    // 一个FIFO队列,包含了所有需要执行的用户脚本
    list *scripts_queue;
} sentinel;

4. 初始化Sentinel状态的masters属性

Sentinel状态中的masters字典记录了所有被Sentinel监视的主服务器的相关信息,其中: ·字典的键是被监视主服务器的名字。 ·而字典的值则是被监视主服务器对应的sentinel.c/sentinelRedisInstance结构

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

对于每个被Sentinel监视的主服务器来说,Sentinel会创建两个连向主服务器的异步网络连接: ·一个是命令连接,这个连接专门用于向主服务器发送命令,并接收命令回复。 ·另一个是订阅连接,这个连接专门用于订阅主服务器的__sentinel__:hello频道

3.2 获取主服务器信息

Sentinel默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。如图:主服务器master有三个从服务器slave0、slave1和slave2,并且一个Sentinel正在连接主服务器,那么Sentinel将持续地向主服务器发送INFO命令,并获得类似于以下内容的回复  Server run_id:7611c59dc3a29aa6fa0609f841bb6a1019008a9c # Replication role:master slave0:ip=127.0.0.1,port=11111,state=online,offset=43,lag=0 slave1:ip=127.0.0.1,port=22222,state=online,offset=43,lag=0 slave2:ip=127.0.0.1,port=33333,state=online,offset=43,lag=0 # Other sections 通过分析主服务器返回的INFO命令回复,Sentinel可以获取以下两方面的信息: ·一方面是关于主服务器本身的信息,包括run_id域记录的服务器运行ID,以及role域记录的服务器角色;

3.3获取从服务器信息

当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构之外,Sentinel还会创建连接到从服务器的命令连接和订阅连接。 在创建命令连接之后,Sentinel在默认情况下,会以每十秒一次的频率通过命令连接向从服务器发送INFO命令,并获得类似于以下内容的回复 # Server run_id:32be0699dd27b410f7c90dada3a6fab17f97899f # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up slave_repl_offset:11887 slave_priority:100 # Other sections

3.4 向主服务器和从服务器发送信息

在默认情况下,Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令: PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>" ·其中以s_开头的参数记录的是Sentinel本身的信息 ·而m_开头的参数记录的则是主服务器的信息

3.5 接收来自主服务器和从服务器的频道信息 

  • 当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令: SUBSCRIBE __sentinel__:hello
  • Sentinel对__sentinel__:hello频道的订阅会一直持续到Sentinel与服务器的连接断开为止。 这也就是说,对于每个与Sentinel连接的服务器,Sentinel既通过命令连接向服务器的__sentinel__:hello频道发送信息,又通过订阅连接从服务器的__sentinel__:hello频道接收信息

  • 对于监视同一个服务器的多个Sentinel来说,一个Sentinel发送的信息会被其他Sentinel接收到,这些信息会被用于更新其他Sentinel对发送信息Sentinel的认知,也会被用于更新其他Sentinel对被监视服务器的认知。
  • 举个例子,假设现在有sentinel1、sentinel2、sentinel3三个Sentinel在监视同一个服务器,那么当sentinel1向服务器的__sentinel__:hello频道发送一条信息时,所有订阅了__sentinel__:hello频道的Sentinel(包括sentinel1自己在内)都会收到这条信息

3.6 接收来自主服务器和从服务器的频道信息 

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

  1. 如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID相同,那么说明这条信息是Sentinel自己发送的,Sentinel将丢弃这条信息,不做进一步处理。
  2. 相反地,如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID不相同,那么说明这条信息是监视同一个服务器的其他Sentinel发来的,接收信息的Sentinel将根据信息中的各个参数,对相应主服务器的实例结构进行更新。

3.7检测主、客观下线状态

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

带箭头的连线显示了Sentinel1和Sentinel2是如何向实例发送PING命令的:

·Sentinel1将向Sentinel2、主服务器master、从服务器slave1和slave2发送PING命令。 ·Sentinel2将向Sentinel1、主服务器master、从服务器slave1和slave2发送PING命令。

实例对PING命令的回复可以分为以下两种情况:

有效回复:实例返回+PONG、-LOADING、-MASTERDOWN三种回复的其中一种。

无效回复:实例返回除+PONG、-LOADING、-MASTERDOWN三种回复之外的其他回复,或者在指定时限内没有返回任何回复。

Sentinel配置文件中的down-after-milliseconds选项指定了Sentinel判断实例进入主观下线所需的时间长度:如果一个实例在down-after-milliseconds毫秒内,连续向Sentinel返回无效回复,那么Sentinel会修改这个实例所对应的实例结构,在结构的flags属性中打开SRI_S_DOWN标识,以此来表示这个实例已经进入主观下线状态。

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

3.8选举领头Sentinel 

  • 当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个Sentinel会进行协商,选举出一个领头Sentinel,并由领头Sentinel对下线主服务器执行故障转移操作。(一旦发现主服务器下线了,一定要选举一个新的主服务器,谁去选择这个新的主服务器呢?  领头的 sentinel 去选择新的主服务器。 谁是领头的 sentinel呢? 看下边的的选举规则、
  • 以下是Redis选举领头Sentinel的规则和方法:
  • 所有在线的Sentinel都有被选为领头Sentinel的资格 ·每次进行领头Sentinel选举之后,不论选举是否成功,所有Sentinel的配置纪元(configuration epoch)的值都会自增一次
  • 在一个配置纪元里面,所有Sentinel都有一次将某个Sentinel设置为局部领头Sentinel的机会,并且局部领头一旦设置,在这个配置纪元里面就不能再更改。
  • 每个发现主服务器进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部领头Sentinel。
  • 当一个Sentinel(源Sentinel)向另一个Sentinel(目标Sentinel)发送SENTINEL is-master-down-by-addr命令,并且命令中的runid参数不是*符号而是源Sentinel的运行ID时,这表示源Sentinel要求目标Sentinel将自己设置为局部领头Sentinel。Sentinel设置局部领头Sentinel的规则是先到先得:最先向目标Sentinel发送设置要求的源Sentinel将成为目标Sentinel的局部领头Sentinel,而之后接收到的所有设置要求都会被目标Sentinel拒绝。
  • 目标Sentinel在接收到SENTINEL is-master-down-by-addr命令之后,将向源Sentinel返回一条命令回复,回复中的leader_runid参数和leader_epoch参数分别记录了目标Sentinel的局部领头Sentinel的运行ID和配置纪元。
  • 源Sentinel在接收到目标Sentinel返回的命令回复之后,会检查回复中leader_epoch参数的值和自己的配置纪元是否相同,如果leader_runid参数的值和源Sentinel的运行ID一致,那么表示目标Sentinel将源Sentinel设置成了局部领头Sentinel。
  • 如果有某个Sentinel被半数以上的Sentinel设置成了局部领头Sentinel,那么这个Sentinel成为领头Sentinel。
  • 因为领头Sentinel的产生需要半数以上Sentinel的支持,并且每个Sentinel在每个配置纪元里面只能设置一次局部领头Sentinel,所以在一个配置纪元里面,只会出现一个领头Sentinel。 如果在给定时限内,没有一个Sentinel被选举为领头Sentinel,那么各个Sentinel将在一段时间之后再次进行选举,直到选出领头Sentinel为止。

3.9故障转移

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

  1. 在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器。
  2. 让已下线主服务器属下的所有从服务器改为复制新的主服务器。
  3. 将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,它就会成为新的主服务器的从服务器。

新的主服务器是怎样挑选出来的?

  1. 领头Sentinel会将已下线主服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:
  2. 删除列表中所有处于下线或者断线状态的从服务器,这可以保证列表中剩余的从服务器都是正常在线的。
  3. 删除列表中所有最近五秒内没有回复过领头Sentinel的INFO命令的从服务器,这可以保证列表中剩余的从服务器都是最近成功进行过通信的。
  4. 删除所有与已下线主服务器连接断开超过down-after-milliseconds*10毫秒的从服务器:down-after-milliseconds选项指定了判断主服务器下线所需的时间,而删除断开时长超过down-after-milliseconds*10毫秒的从服务器,则可以保证列表中剩余的从服务器都没有过早地与主服务器断开连接,换句话说,列表中剩余的从服务器保存的数据都是比较新的。
  5. 之后,领头Sentinel将根据从服务器的优先级,对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器。 如果有多个具有相同最高优先级的从服务器,那么领头Sentinel将按照从服务器的复制偏移量,对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器(复制偏移量最大的从服务器就是保存着最新数据的从服务器)。 最后,如果有多个优先级最高、复制偏移量最大的从服务器,那么领头Sentinel将按照运行ID对这些从服务器进行排序,并选出其中运行ID最小的从服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL Workbench使用入门

软件介绍 MySQL Workbench 是可视化数据库设计软件&#xff0c;为数据库管理员和开发人员提供了一整套可视化的数据库操作环境&#xff0c;主要功能有数据库设计与模型建立、SQL 开发&#xff08;取代 MySQL Query Browser&#xff09;、数据库管理&#xff08;取代 MySQL Adm…

【Vue框架】Vue2中element-ui/mint-ui组件库——element-ui引入组件以及使用案例、mint-ui引入组件及使用案例

文章目录一、element-ui/mint-ui组件库1.1 element-ui使用步骤1.1.1 引入组件1.1.2 修改 .babelrc文件1.2 mint-ui的使用1.2.1 安装引入组件1.2.2 Mint-ui相关组件一、element-ui/mint-ui组件库 element-ui 提供了大量的组件&#xff0c;如&#xff1a;布局组件、表单组件、JS…

运行时内存数据区之虚拟机栈——动态链接、方法返回地址与一些附加信息

动态链接&#xff08;Dynamic Linking&#xff09;——指向运行时常量池的方法引用 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。比如&#xff1a;invokedynamic指令。…

算法 DAY24 回溯 || 第77题. 组合 216.组合总和III 17.电话号码的字母组合 39. 组合总和

前置知识 回溯算法模板框架如下&#xff1a;void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点;backtracking(路径&#xff0c;选择列表); // 递归回溯&am…

rk3568点亮LCD(lvds)

rk3568 Android11/12 适配 lvds 屏 LVDS&#xff08;Low Voltage Differential Signal&#xff09;即低电压差分信号。1994年由美国国家半导体&#xff08;NS&#xff09;公司为克服以TTL电平方式传输宽带高码率数据时功耗大、电磁干扰大等缺点而研制的一种数字视频信号传输方…

堆的实现

思维导图 堆的概念 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事…

【LeetCode】剑指 Offer 50. 第一个只出现一次的字符 p243 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/ 1. 题目介绍&#xff08;50. 第一个只出现一次的字符&#xff09; 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。 【测…

al文章生成-文章生成工具

ai文章生成器 AI文章生成器是一种利用人工智能和自然语言处理技术生成文章的工具。它使用先进的算法、机器学习和深度学习技术&#xff0c;深度挖掘和提取大量数据背后的信息&#xff0c;自主学习并合并新的信息&#xff0c;生成优质、原创的文章。 使用AI文章生成器的优点如下…

liunx mysql 主从同步设置 关键点

主库MySQL配置文件&#xff1a;该配置文件默认是在 /etc/my.cnf [mysqld] max_allowed_packet256M server-id1 log-binmysql-bin replicate-do-dbweb auto_increment_increment2 auto_increment_offset1 binlog_ignore_dbsys general_logon general_log_file/v…

Qt下载以及调试

1.概念 Qt是一个跨平台的基于C图形用户界面应用程序框架。 常见GUI&#xff1a; Qt&#xff1a;支持多平台&#xff1b;支持css&#xff1b;面向对象特性体现突出&#xff1b;发展趋势良好&#xff1b; MFC&#xff1a;仅在Windows&#xff1b;运行程序效率高&#xff1b;库安…

外包干了四年,感觉废了..

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

如何利用ventoy制作Linux to go (把deepin放到U盘里)

准备工作 最新版本 – 深度科技社区 (deepin.org) deepin镜像官方下载即可 Releases ventoy/vtoyboot GitHub ventoy启动插件选择1.0.29版本 Downloads – Oracle VM VirtualBox VirtualBox虚拟机官网 ventoy下载 VentoyRelease (lanzoui.com) 选择下载1.0.29版本 vento…

表格软件界的卷王,Excel、access、foxpro全靠边,WPS:真荣幸

Excel和Access就是表格软件的选择&#xff1f; 现在&#xff0c;铺天盖地的Excel的技能教程可谓是满天飞&#xff0c;有网上的教程&#xff0c;也有视频直播课程。 很多办公人员用Excel这种表格软件与VBA结合&#xff0c;甚至用不遗余力去学习Python编程语法&#xff0c;但Exce…

2023年会计师事务所研究报告

第一章 行业发展概况 1.1 行业概况 会计师事务所是专门从事财务、税务等领域的专业服务机构&#xff0c;其服务范围涵盖了审计、会计、税务、咨询等多个方面。 近年来&#xff0c;随着全球经济的不断发展和国际贸易的增加&#xff0c;会计师事务所行业也得到了快速发展。据统…

G8期刊《全体育》期刊简介及投稿要求

G8期刊《全体育》期刊简介及投稿要求 《全体育》是由湖南体育产业集团有限公司主管、体坛传媒集团股份有限公司主办、中教体育 出版发行的体育综合性期刊。 主管&#xff1a;湖南体育产业集团有限公司 主办&#xff1a;体坛传媒集团股份有限公司 国内刊号&#xff1a;CN4…

「实战教程」如何使用POI读取模板PPT填充数据并拼接至目标文件

文章目录一、PPT文件格式介绍1、PPT文件格式的概述2、HSLF和XSLF的区别3、如何选择合适的POI类库二、SlideShow三、读取PPT文件1. 加载PPT文件2. 获取PPT文件中的幻灯片3. 获取幻灯片中的形状元素四、修改PPT文件内容1. 幻灯片操作1.1 新增幻灯片1.2 删除幻灯片1.3 移动幻灯片1…

MySQL中count(1)和count(*)哪个性能好?

当我们对某一张表中的数据需要统计数量的时候&#xff0c;我们通常会用到count(1)、count(*)或者count(字段)&#xff0c;而这三种哪个方式的count效率最高呢&#xff1f;先来说结论&#xff1a; count(1) count(*) > count(字段) 为什么会得到如上的结论&#xff0c;下面来…

xilinx FPGA FIFO IP核的使用(VHDLISE)

1.新建工程和ip核文件 下图显示了一个典型的写操作。拉高WR_EN&#xff0c;导致在WR_CLK的下一个上升边缘发生写入操作。因为FIFO未满&#xff0c;所以WR_ACK输出1&#xff0c;确认成功的写入操作。当只有一个附加的单词可以写入FIFO时&#xff0c;FIFO会拉高ALMOST_FULL标志。…

图数据结构与算法

什么是图数据的结构 图是由顶点和边组成的非线性数据结构。顶点有时也称为节点,边是连接图中任意两个节点的线或弧。更正式地说,图由一组顶点 ( V ) 和一组边 ( E ) 组成。该图由 G(E, V) 表示。 图的组成部分 顶点:顶点是图的基本单位。有时,顶点也称为顶点或节点。每个节…

私有化部署VideoTogether一起看视频

本文折腾始于 2022 年 9 月&#xff0c;但因为种种原因并未写完&#xff0c;最近&#xff0c;因为有朋友需要&#xff0c;又重新开始捡了起来&#xff0c;然而&#xff0c;我发现官方已经把私有化部署的相关文档删了&#xff0c;原因不得而知。 什么是 VideoTogether ? VideoT…