继《Redis设计与实现》第十六章总结一:Sentinel状态封装
16.4 向主从服务器分别发送信息
Sentinel默认以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:
此命令向服务器的_sentinel _:hello频道发送一条消息,消息的内容由多个参数组成:
以 _s开头的参数记录的是Sentinel本身的信息,参数意义如下图:
以m_开头的参数记录的则是主服务器的信息,如果Sentinel正在监视的是主服务器,那么这些参数记录的就是主服务器的信息;如果正在监视的是从服务器,则为从服务器正在复制的主服务器的信息;参数意义如下图:
16.5 接收来自主服务器和从服务器的频道信息
当Sentine与一个主或从服务器建立起订阅连接后,Sentinel就会通过订阅连接,向服务器发送以下命令:
SUBSCRIBE _sentinel _:hello
来订阅频道,一直持续到Sentinel与服务器的连接断开为止
因此,Sentinel与服务器类似全双工:
对于监视同一个服务器的多个Sentinel来说,一个Sentinel发送的消息会被其他Sentinel接收到
作用:被其他Sentinel用于更新对发送消息的Sentinel的认知和对被监视服务器的认知
当一个Sentinel从频道中收到信息时:
Sentinel会提取出信息中的Sentinel IP地址、Sentinel端口号、Sentinel运行ID等八个参数,并进行检查:
1.如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID相同,说明这条信息是Sentinel自己发送的,无需做任何处理,丢弃即可
2.如果信息中记录的Sentinel运行ID和接收信息的Sentinel的运行ID不相同,说明这条信息是监视同一个服务器的其他Sentinel发送的;接收信息的Sentinel将根据信息中的各个参数,对相应主服务器的实例结构sentinelRedisInstance进行更新(具体更新为16.5.1)
16.5.1 更新sentinels字典
Sentinel为主服务器创建的实例结构sentinelRedisInstance中的sentinels字典属性:保存了Sentinel本身和所有同样监视这个主服务器的其他Sentinel的资料
- 保存其他Sentinel的实现方式
因为对于监视同一个服务器的多个Sentinel来说,一个Sentinel发送的消息(源Sentinek)会被其他Sentinel接收到(目标Sentinel),所以当一个Sentinel接收到其他Sentinel发来的消息时,可以提取出如下参数信息:
然后做如下的判断和操作:
例子:127.0.0.1:26379接收到如下信息:
说明总共有三个Sentinel正在监视主服务器
第一条信息为自己,会被忽略,二三则会根据消息内容,对sentinels字典中127.0.0.1:26380、127.0.0.1:26381所对应的实例结构进行更新(参考“当一个Sentinel从频道中收到信息时”)
则Sentinel127.0.0.1:26379为主服务器127.0.0.1:6329创建的实例结构sentinels字典为:
16.5.2 创建连向其他Sentinel的命令连接
监视同一个服务器的Sentinel之间也会两两互相建立命令连接
作用:用来对Sentinel实现主观下线检测和客观下线检测
注意:无需创建订阅连接
16.6 检测主观下线状态
Sentinel默认以每秒一次的频率向所有与它创建了命令连接的实例,包括主服务器、从服务器、其他Sentinel在内发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线
回复可以分为以下两种情况:
主观下线的选项:down-atfer-milliseconds
例子:down-atfer-milliseconds设置为50000毫秒,主服务器master连续50000毫秒向Sentinel返回无效回复时,Sentinel就将master标记为下线,且打开SRI_S_DOWN标识
也可以用来判断主服务器下所有的从服务器,以及所有同样监视这个主服务器的其他Sentinel的主观下线状态
多个Sentinel设置的主观下线时长可以不同
16.7 检查客观下线状态
判断是否真的下线:
16.7.1 发送SENTINEL is-master-down-by-addr命令
使用SENTINEL is-master-down-by-addr < ip > < port > < current_epoch > < runid >命令来询问其他Sentinel是否同意主服务器下线,参数意义如下:
16.7.2 接收SENTINEL is-master-down-by-addr命令
内容:达到一定数量,则打开SRI_O_DOWN,表示客观下线
数量的配置选项为:quorum
不同Sentinel判断客观下线的条件可以不同
16.8 选举领头Sentinel
当一个主服务器被判断为客观下线时,监视这个下线主服务器器的各个Sentinel会进行协商,选举出一个领头Sentinel,并由领头Sentinel对下线主服务器执行故障转移操作
选举的规则:
例子:
假设现在有三个Sentinel正在监视同一个主服务器,且这三个Sentinel之前已经通过SENTINEL is-master-down-by-addr命令确认主服务器进入了客观下线状态;
那么为了选出领头Sentinel,三个Sentinel将再次向其他Sentinel发送SENTINEL is-master-down-by-addr命令,和检测客观下线时发送的命令不同,此次带有Sentinel自己的运行ID,即runid参数,类似如下
接收到此命令的其他Sentinel如果还没有设置局部领头Sentinel的话,就将收到的命令的指定运行IDSentinel设置为自己的局部领头,并返回设置成功回复,类似如下
接收到命令回复的Sentinel则根据回复统计出有多少Sentinel将自己设置成了局部领头,配置纪元和ID相同即可
根据命令请求发送的先后顺序不同,可能会有某个Sentinel的命令比其它Sentinel发送的相同命令都更快到达,并最终胜出选举,成为真正的领头,此时就可以开始对主服务器执行故障转移操作了
16.9 故障转移
在选举产生出领头Sentinel后,领头Sentinel将对已下线的主服务器执行故障转移操作
分为三个步骤:
接下来逐一介绍
16.9.1 选出新的主服务器
领头Sentinel选出一个从服务器,发送SLAVEOF no one命令,将其转换为主服务器
挑选步骤:
发送SLAVEOF no one命令之后,领头Sentinel会以每秒一次的频率(平时是每十秒一次)向被升级的服务器发送INFO命令,并观察命令回复中的角色信息;当被升级服务器的role从slave变为master时,领头master就知道被选中的从服务器已经顺利升级为主服务器了
16.9.2 修改从服务器的复制目标
新的主服务器出现之后,领头Sentinel下一步要做的是让已下线主服务器属下的从服务器去复制新的主服务器
实现:领头Sentinel向从服务器发送SLAVEOF < newMaster_ip > < newMaster_port >命令
16.9.3 将旧的主服务器变为从服务器
当旧的主服务器重新上线时,领头Sentinel就会向它发送SLAVEOF < newMaster_ip > < newMaster_port >命令,让它成为新的主服务器的从服务器