Sentinel(哨岗、哨兵)是 Redis 的高可用性(hign availability)解决方案:由一个或多个 Sentinel 实例(instance)组成的 Sentinel 系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求
redis incrby?图 16-1 展示了一个 Sentinel 系统监视服务器的例子,其中:
假设这时,主服务器 server1 进入下线状态,那么从服务器 server2、server3、server4 对主服务器的复制操作将被中止,并且 Sentinel 系统会察觉到 server1 已下线,如图 16-2 所示(下线的服务器用虚线表示)
当 server1 的下线时长超过用户设定的下线时长上限时,Sentinel 系统就会对 server1 执行故障转移操作:
图 16-3 展示了 S恩听饿了系统将 server2 升级为新的主服务器,并让服务器 server3 和 server4 成为 server2 的从服务器的过程
redis cluster原理,
之后,如果 server1 重新上线的话,它将被 Sentinel 系统降级为 server2 的从服务器,如图 16-4 所示
启动一个 Sentinel 可以使用命令:
$ redis-sentinel sentinel.conf
或者命令:
$ redis-server sentinel.conf --sentinel
redis docker,这两个命令的效果完全相同
当一个 Sentinel 启动时,它需要执行以下步骤:
首先,因为 Sentinel 本质上只是一个运行在特殊模式下的 Redis 服务器,所以启动 Sentinel 的第一步,就是初始化一个普通的 Redis 服务器
不过,因为 Sentinel 执行的工作和普通 Redis 服务器执行的工作不同,所以 Sentinel 的初始化过程和普通 Redis 服务器的初始化过程并不完全相同
例如,普通服务器在初始化时会通过载入 RDB 文件或者 AOF 文件来还原数据库状态,但是因为 Sentinel 并不使用数据库,所以初始化 Sentinel 时就不会载入 RDB 文件或者 AOF 文件
redis 集群。表 16-1 展示了 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 作为服务器的命令表,并且其中的 INFO 命令会使用 Sentinel 模式下的专用实现 sentinel.c/sentinelInfoCommand 函数,而不是普通 Redis 服务器使用的实现 redis.c/infoCommand 函数:
sentinelcmds 命令表也解释了为什么在 Sentinel 模式下,Redis 服务器不能执行诸如 SET、DBSIZE、EVAL 等等这些命令,因为服务器根本没有在命令表中载入这些命令。PING、SENTINEL、INFO、SUBSCRIBE、PSUBSCRIBE 和 PUNSUBSCRIBE 这七个命令就是客户端可以对 Sentinel 执行的全部命令了
redis基础?在应用了 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;
Sentinel 状态中的 masters 字典记录了所有被 Sentinel 监视的主服务器的相关信息,其中:
每个 sentinelRedisInstance 结构(后面简称 “实例结构”)代表一个被 Sentinel 监视的 Redis 服务器实例(instance),这个实例可以是主服务器、从服务器,或者另外一个 Sentinel
实例结构包含的属性非常多,以下代码展示了实例结构在表示主服务器时使用的其中一部分属性:
typedef struct sentinelRedisInstance{//标识值,记录了实例的类型,以及该实例的当前状态int flags;//实例的名字//主服务器的名字由用户在配置文件中设置//从服务器以及 Sentinel 的名字由 Sentinel 自动设置//格式为 ip:port,例如 "127.0.0.1:16379"char *name;//实例的运行 IDchar *runid;//配置纪元,用于实现故障转移uint64_t config_epoch;//实例的地址sentinelAddr *addr;//SENTINEL down-after-milliseconds 选项设定的值//实例无响应多少毫秒之后才会被判断为主观下线(subjectively down)mstime_t down_After_period;//SENTINEL monitor <master-name> <IP> <port> <quorum> 选项中的 quorum 参数//判断这个实例为客观下线(objectively down)所需的支持投票数量int quorum;//SENTINEL parallel-syncs <master-name> <number> 选项的值//在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量int parallel_syncs;//SENTINEL failover-timeout <master-name> <ms> 选项的值//刷新故障迁移状态的最大时限mstime_t failover_timeout;//...
}sentinelRedisInstance;
sentinelRedisInstance.addr 属性是一个指向 sentinel.c/sentinelAddr 结构的指针,这个结构保存着实例的 IP 地址和端口号:
typedef struct sentinelAddr{char *ip;int port;
}sentinelAddr;
redis设计与实现,对 Sentinel 状态的初始化将引发对 masters 字典的初始化,而 masters 字典的初始化是根据被载入的 Sentinel 配置文件来进行的
举个例子,如果用户在启动 Sentinel 时,指定了包含以下内容的配置文件:
那么 Sentinel 将为主服务器 master1 创建如图 16-5 所示的实例结构,并为主服务器 master2 创建如图 16-6 所示的实例结构,而这两个实例结构又会被保存到 Sentinel 状态的 masters 字典中,如图 16-7 所示
redis持久化、初始化 Sentinel 的最后一步是创建连向被监视主服务器的网络连接,Sentinel 将成为主服务器的客户端,它可以向服务器发送命令,并从命令回复中获取相关的信息
对于每个被 Sentinel 监视的主服务器来说,Sentinel 会创建两个连向主服务器的异步网络连接:
为什么有两个连接?
在 Redis 2.8 的发布与订阅功能中,被发送的信息都不会保存在 Redis 服务器里面,如果在信息发送时,想要接收信息的客户端不在线或者断线,那么这个客户端就会丢失这条信息。因此,为了不丢失 __sentinel__:hello 频道的任何信息,Sentinel 必须专门用一个订阅连接来接收该频道的信息
另一方面,除了订阅频道之外,Sentinel 还必须向主服务器发送命令,以此来与主服务器进行通信,所以 Sentinel 还必须向主服务器创建命令连接
redis数据库设计?此外,因为 Sentinel 需要与多个实例创建多个网络连接,所以 Sentinel 使用的是异步连接
图 16-8 展示了一个 Sentinel 向被它监视的两个主服务器 master1 和 master2 创建命令连接和订阅连接的例子
Sentinel 默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送 INFO 命令,并通过分析 INFO 命令的回复来获取主服务器的当前信息
举个例子,假设如图 16-9 所示,主服务器 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
redis,通过分析主服务器返回的 INFO 命令回复,Sentinel 可以获取以下两方面的信息:
根据 run_id 域 和 role 域记录的信息,Sentinel 将对主服务器的实例结构进行更新,例如,主服务器重启之后,它的运行 ID 就会和实例结构之前保存的运行 ID 不同,Sentinel 检测到这一情况之后,就会对实例结构的运行 ID 进行更新
至于主服务器返回的从服务器信息,则会被用于更新主服务器实例结构的 slaves 字典,这个字典记录了主服务器属下从服务器的名单:
Sentinel 在分析 INFO 命令中包含的从服务器信息时,会检查从服务器对应的实例结构是否已经存在于 slaves 字典:
对于我们之前列举的主服务器 master 和三个从服务器 slave0、slave1 和 slave2 的例子来说,Sentinel 将分别为三个从服务器创建它们各自的实例结构,并将这些结构保存到主服务器实例结构的 slaves 字典里面,如图 16-10 所示
k8s redis集群,
注意对比图中主服务器实例结构和从服务器实例结构之间的区别:
当 Sentinel 发现主服务器有新的从服务器出现时,Sentinel 除了会为这个新的从服务器创建相应的实例结构之外,Sentinel 还会创建连接到从服务器的命令连接和订阅连接
举个例子,对于图 16-10 所示的主从服务器关系来说,Sentinel 将对 slave0、slave1 和 slave2 三个从服务器分别创建命令连接和订阅连接,如图 16-11 所示
redis sentinel集群?在创建命令之后,Sentinel 在默认情况下,会以每十秒一次的频率通过命令连接向从服务器发送 INFO 命令,并获得类似于以下内容的回复:
根据 INFO 命令的回复,Sentinel 会提取出以下信息:
根据这些信息,Sentinel 会对从服务器的实例结构进行更新,图 16-12 展示了 Sentinel 根据上面的 INFO 命令回复对从服务器的实例结构进行更新之后,实例结构的样子:
在默认情况下,Sentinel 会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:
PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
这条命令向服务器的 __sentinel__:hello 频道发送了一条信息,信息的内容由多个参数组成:
以下是一条 Sentinel 通过 PUBLISH 命令向主服务器发送的信息示例:
"127.0.0.1,26379,e955b4c85598ef5b5f055bc7ebf5e828dbed4fa,0,mymaster,127.0.0.1,6379,0"
这个示例包含了以下信息:
当 Sentinel 与一个主服务器或者从服务器建立起订阅连接之后,Sentinel 就会通过订阅连接,向服务器发送以下命令:
SUBSCRIBE __sentinel__:hello
Sentinel 对 __sentinel__:hello 频道的订阅会一直持续到 Sentinel 与服务器的连接断开为止
这也就是说,对于每个与 Sentinel 连接的服务器,Sentinel 既通过命令连接向从服务器的 __sentinel__:hello 频道发送信息,又通过订阅连接从服务器的 _sentinel_:hello 频道接收信息,如图 16-13 所示
对于监视同一个服务器的多个 Sentinel 来说,一个 Sentinel 发送的信息会被其他Sentinel 接收到,这些信息会被用于更新其他 Sentinel 对发送信息 Sentinel 的认知,也会被用于更新其他 Sentinel 对被监视服务器的认知
举个例子,假设现在有 sentinel1、sentinel2、sentinel3 三个 Sentinel 在监视同一个服务器,那么当 sentinel1 向服务器的 __sentinel__:hello 频道发送一条信息时,所有订阅了 _sentinel_:hello 频道的 Sentinel(包括 sentinel1 自己在内)都会收到这条信息,如图 16-14 所示
当一个 Sentinel 从 __sentinel__:hello 频道收到一条信息时,Sentinel 会对这条信息进行分析,提取出信息中的 Sentinel IP 地址、Sentinel 端口号、Sentinel 运行 ID 等八个参数,并进行以下检查:
Sentinel 为主服务器创建的实例结构中的 sentinels 字典保存了除 Sentinel 本身之外,所有同样监视这个主服务器的其他 Sentinel 的资料:
当一个 Sentinel 接收到其他 Sentinel 发来的信息时(我们称呼发送信息的 Sentinel 为源 Sentinel,接收信息的 Sentinel 为目标 Sentinel),目标 Sentinel 会从信息中分析并提取出以下两方面参数:
根据信息中提取出的主服务器参数,目标 Sentinel 会在自己的 Sentinel 状态的 masters 字典中查找相应的主服务器实例结构,然后根据提取出的 Sentinel 参数,检查主服务器实例结构的 sentinels 字典中,源 Sentinel 的实例结构是否存在:
举个例子,假设分别有 127.0.0.1:26379、127.0.0.1:26380、127.0.0.1:26381 三个 Sentinel 正在监视主服务器 127.0.0.1:6379,那么当 127.0.0.1:26379 这个 Sentinel 接收到以下信息时:
Sentinel 将执行以下动作:
图 16-15 展示了 Sentinel 127.0.0.1:26379 为主服务器 127.0.0.1:6379 创建的实例结构,以及结构中的 sentinels 字典
和 127.0.0.1:26379 一样,其他两个 Sentinel 也会创建类似于图 16-15 所示的 sentinels 字典,区别在于字典中保存的 Sentinel 信息不同:
因为一个 Sentinel 可以通过分析接收到的频道信息来获知其他 Sentinel 的存在,并通过发送频道信息来让其他 Sentinel 知道自己的存在,所以用户在使用 Sentinel 的时候并不需要提供各个 Sentinel 的地址信息,监视同一个主服务器的多个 Sentinel 可以自动发现对方
当 Sentinel 通过频道信息发现一个新的 Sentinel 时,它不仅会为新 Sentinel 在 sentinels 字典中创建相应的实例结构,还会创建一个连向新 Sentinel 的命令连接,而新 Sentinel 也同样会创建连向这个 Sentinel 的命令连接,最终监视同一主服务器的多个 Sentinel 将形成相互连接的网络:Sentinel A 有连向 Sentinel B 的命令连接,而 Sentinel B 也有连向 Sentinel A 的命令连接
图 16-16 展示了三个监视同一主服务器的 Sentinel 之间是如何互相连接的
使用命令连接相连的各个 Sentinel 可以通过向其他 Sentinel 发送命令请求来进行信息交换
Sentinel 之间不会创建订阅连接
Sentinel 在连接主服务器或者从服务器时,会同时创建命令连接和订阅连接,但是在连接其他 Sentienl 时,却只会创建命令连接,而不创建订阅连接。这是因为 Sentinel 需要通过接收主服务器或者从服务器发来的频道信息来发现未知的新 Sentinel,所以才需要建立订阅连接,而相互已知的 Sentinel 只要使用命令连接来进行通信就足够了
在默认情况下,Sentinel 会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他 Sentinel 在内)发送 PING 命令,并通过实例返回的 PING 命令回复来判断实例是否在线
在图 16-17 展示的例子中,带箭头的连线显示了 Sentinel1 和 Sentinel2 是如何向实例发送 PING 命令的:
实例对 PING 命令的回复可以分为以下两种情况:
Sentinel 配置文件中的 down-after-milliseconds 选项指定了 Sentinel 判断实例进入主观下线所需的时间长度:如果一个实例在 down-after-milliseconds 毫秒内,连续向 Sentinel 返回无效回复,那么 Sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中打开 SRI_S_DOWN 标识,以此来表示这个实例已经进入主观下线状态
以图 16-17 展示的情况为例子,如果配置文件指定 Sentinel1 的 down-after-milliseconds 选项的值为 50000 毫秒,那么当主服务器 master 连续 50000 毫秒都向 Sentinel1 返回无效回复时,Sentinel1 就会将 master 标记为主观下线,并在 master 所对应的实例结构的 flags 属性中打开 SRI_S_DOWN 标识,如图 16-18 所示
主观下线时长选项的作用范围
用户设置得 down-after-milliseconds 选项的值,不仅会被 Sentinel 用来判断主服务器的主观下线状态,还会被用于判断主服务器属下的所有从服务器,以及所有同样监视这个主服务器的其他 Sentinel 的主观下线状态。举个例子,如果用户向 Sentinel 设置了以下配置:
sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 50000
那么 50000 毫秒不仅会成为 Sentinel 判断 master 进入主观下线的标准,还会成为 Sentinel 判断 master 属下所有从服务器,以及所有同样监视 master 的其他 Sentinel 进入主观下线的标准
多个 Sentinel 设置的主观下线时长可能不同
down-after-milliseconds 选项另一个需要注意的地方是,对于监视同一个主服务器的多个 Sentinel 来说,这些 Sentinel 所设置的 down-after-milliseconds 选项的值也可能不同,因此,当一个 Sentinel 将主服务器判断为主观下线时,其他 Sentinel 可能仍然会认为主服务器处于在线状态。举个例子,如果 Sentinel1 载入了以下配置:
sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 50000
而 Sentinel2 则载入了以下配置:
sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 10000
那么当 master 的断线时长超过了 10000 毫秒之后,Sentinel2 会将 master 判断为主观下线,而 Sentienl1 却认为 master 仍然在线。只有当 master 的断线时长超过 50000 毫秒之后,Sentinel1 和 Sentinel2 才会都认为 master 进入了主观下线状态
当 Sentinel 将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线了,它会同样监视这一主服务器的其他 Sentinel 进行询问,看他们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。当 Sentinel 从其他 Sentinel 那里接收到足够数量的已下线判断之后,Sentinel 就会将从服务器判断为客观下线,并对主服务器执行故障转移操作
Sentinel 使用:
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
命令询问其他 Sentinel 是否同意主服务器已下线,命令中的各个参数的意义如表 16-4 所示
举个例子,如果被 Sentinel 判断为主观下线的主服务器的 IP 为 127.0.0.1,端口号为 6379,并且 Sentinel 当前的配置纪元为 0,那么 Sentinel 将向其他 Sentinel 发送以下命令:
SENTINEL is-master-down-by-addr 127.0.0.1 6379 0 *
当一个 Sentinel(目标 Sentinel)接收到另一个 Sentinel(源 Sentinel)发来的 SENTINEL is-master-down-by 命令时,目标 Sentinel 会分析并取出命请求中包含的各个参数,并根据其中的主服务器 IP 和端口号,检查主服务器是否已下线,然后向源 Sentinel 返回一条包含三个参数的 Multi Bulk 回复作为 SENTINEL is-master-down-by 命令的回复:
1) <down_state>
2) <leader_runid>
3) <leader_epoch>
表 16-5 分别记录了这三个参数的意义
举个例子,如果一个 Sentinel 返回以下回复作为 SENTINEL is-master-down-by-addr 命令的回复:
1) 1
2) *
3) 0
那么说明 Sentinel 也同意主服务器已下线
根据其他 Sentinel 发回的 SENTINEL is-master-down-by-addr 命令回复,Sentinel 将统计其他 Sentinel 同意主服务器已下线的数量,当这一数量达到配置指定的判断客观下线所需的数量时,Sentinel 会将主服务器实例结构 flags 属性的 SRI_O_DOWN 标识打开,表示主服务器已经进入客观下线状态,如图 16-19 所示
客观下线状态的判断条件
当认为主服务器已经进入下线状态的 Sentinel 的数量,超过 Sentinel 配置中设置得 quorum 参数的值,那么该 Sentinel 就会认为主服务器已经进入客观下线状态。比如说,如果 Sentinel 在启动时载入了以下配置:
sentinel monitor master 127.0.0.1 6379 2
那么包括当前 Sentinel 在内,只要总共有两个 Sentinel 认为主服务器已经进入了下线状态,那么当前 Sentinel 就将主服务器判断为客观下线。又比如说,如果 Sentinel 在启动时载入了以下配置:
sentinel monitor master 127.0.0.1 6379 5
那么包括当前 Sentinel 在内,总共要有五个 Sentinel 都认为主服务器已经下线,当前 Sentinel 才会将主服务器判断为客观下线
不同 Sentinel 判断客观下线的条件可能不同
对于监视同一个主服务器的多个 Sentinel 来说,它们将主服务器判断为客观下线的条件可能也不同:当一个 Sentinel 将主服务器判断为客观下线时,其他 Sentinel 可能并不是那么认为的。比如说,对于监视同一个主服务器的五个 Sentinel 来说,如果 Sentinel1 在启动时载入了以下配置:
sentinel monitor master 127.0.0.1 6379 2
那么当五个 Sentinel 中有两个 Sentinel 认为主服务器已经下线时,Sentinel1 就会将主服务器判断为客观下线
而对于载入了以下配置的 Sentinel2 来说:
sentinel monitor master 127.0.0.1 6379 5
仅有两个 Sentinel 认为主服务器已下线,并不会令 Sentinel2 将主服务器判断为客观下线
当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个 Sentinel 会进行协商,选举出一个领头 Sentinel,并由领头 Sentinel 对下线主服务器执行故障转移操作
以下是 Redis 选举领头的规则和方法:
为了熟悉以上规则,让我们来看一个选举领头 Sentinel 的过程
假设现在有三个 Sentinel 正在监视同一个主服务器,并且这三个 Sentinel 之前已经通过 SENTINEL is-master-down-by-addr 命令确认主服务器进入了客观下线状态,如图 16-20 所示
那么为了选出领头 Sentinel,三个 Sentinel 将再次向其他 Sentinel 发送 SENTINEL is-master-down-by-addr 命令,如图 16-21 所示
和检测客观下线状态时发送的 SENTINEL is-master-down-by-addr 命令不同,Sentinel 这次发送的命令会带有 Sentinel 自己的运行 ID,例如:
SENTINEL is-master-down-by-addr 127.0.0.1 6379 e955b4c85598ef5b5f055bc7ebfd5e8828dbed4fa
如果接收到这个命令的 Sentinel 还没有设置局部领头 Sentinel 的话,它就会将运行 ID 为 e955b4c85598ef5b5f055bc7ebfd5e828dbed4fa 的 Sentinel 设置为自己的局部领头 Sentinel,并返回类似以下的命令回复:
1) 1
2) e955b4c85598ef5b5f055bc7ebfd5e8828dbed4fa
3) 0
然后接收到命令回复的 Sentinel 就可以根据这一回复,统计出有多少个 Sentinel 将自己设置成了局部领头 Sentinel
根据命令请求发送的先后顺序不同,可能会有某个 Sentinel 的 SENTINEL is-master-down-by-addr 命令比起其他 Sentinel 发送的相同命令都更块到达,并最终胜出领头 Sentinel 的选举,然后这个领头 Sentinel 就可以开始对主服务器执行故障转移操作了
在选举产生出领头 Sentinel 之后,领头 Sentinel 将对已下线的主服务器执行故障转移操作,该操作包含以下三个步骤:
故障转移操作第一步要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好、数据完整的从服务器,然后向这个从服务器发送 SLAVEOF no one 命令,将这个从服务器转换为主服务器
新的主服务器是怎样挑选出来的
领头 Sentinel 会将已下线出服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:
之后,领头 Sentinel 将根据从服务器的优先级,对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器
如果有多个具有相同最高优先级的从服务器,那么领头 Sentinel 将按照从服务器的复制偏移量,对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器(复制偏移量最大的从服务器就是保存着最新数据的从服务器)
最后,如果有多个优先级最高、复制偏移量最大的从服务器,那么领头 Sentinel 将按照运行 ID 对这些从服务器及逆行排序,并选出其中运行 ID 最小的从服务器
图 16-22 展示了在一次故障转移操作中,领头 Sentienl 向被选中的从服务器 server2 发送 SLAVEOF no one 命令的情形
在发送 SLAVEOF no one 命令之后,领头 Sentinel 会以每秒一次的频率(平时是每十秒一次),向被升级的从服务器发送 INFO 命令,并观察命令回复中的角色(role)信息,当被升级服务器的 role 从原来的 slave 变为 master 时,领头 Sentinel 就知道被选中的从服务器已经顺利升级为主服务器了
例如,在图 16-22 展示的例子中,领头 Sentinel 会一直向 server2 发送 INFO 命令,当 server2 返回的命令回复从:
# Replication
role:slave
...
# Ohter sections
...
变为:
# Replication
role:master
...
# Ohter sections
...
的时候,领头 Sentinel 就知道 server2 已经成功升级为主服务器了
图 16-23 展示额 server2 升级成功之后,各个服务器和领头 Sentinel 的样子
当新的主服务器出现之后,领头 Sentinel 下一步要做的就是,让已下线主服务器属下的所有从服务器去复制新的主服务器,这一动作可以通过向从服务器发送 SLAVEOF 命令来实现
图 16-24 展示了在故障转移操作中,领头 Sentinel 向已下线主服务器 server1 的两个从服务器 server3 和 server4 发送 SLAVEOF 命令,让它们复制新的主服务器 server2 的例子
图 16-25 展示了 server3 和 server4 成为 server2 的从服务器之后,各个服务器以及领头 Sentinel 的样子
故障转移操作最后要做的就是,将已下线的主服务器设置为新的主服务器的从服务器。比如说,图 16-26 就展示了被领头 Sentinel 设置为从服务器之后,服务器 sever1 的样子
因为旧的主服务器就已经下线,所以这种设置是保存在 server1 对应的实例结构里面的,当 server1 重新上线时,Sentinel 就会向它发送 SLAVEOF 命令,让它成为 server2 的从服务器
例如,图 16-27 就展示了 server1 重新上线并成为 server2 的从服务器的例子
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态