16.6 检测主观下线状态
Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例,包括主服务器、从服务器、其他Sentinel在内发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。
配置文件的down-after-millseconds
选项指定了Sentinel判断实例进入主观下线所需要的时间长度:如果一个实例在down-after-millseconds
毫秒内连续向Sentinel返回无效回复,那么Sentinel会修改这个实例所对应的实例结构,在结构的flags
属性中打开SRI_S_DOWN
标识,以此表示这个实例已进入主观下线状态
多个Sentinel设置的主观下线时长也可以不同
16.7 检查客观下线状态
当Sentinel将这一主服务器判断为主观下线后,为了确认这个主服务器是否真的下线,它会向同样监视这一主服务器的其他Sentinel进行询问,看他们是否也认为主服务器已经进入了下线状态(可以是主观下线,也可以是客观下线),当收到足够数量的已下线判断之后,Sentinel就会将主服务器判定为客观下线,并进行故障转移操作。
16.7.1 发送Sentinel命令
发送SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
命令,询问其他Sentinel是否同意主服务器已下线。
其中current_epoch
表示Sentinel当前的配置纪元,用于选举领头Sentinel;runid
可以是*或是Sentinel的运行ID,*表示检测主服务器的客观下线,Sentinel的运行ID用于选举领头Sentinel
16.7.3 接收Sentinel命令
当目标Sentinel收到源Sentinel发来的SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
命令时,目标Sentinel会分析并取出命令请求里包含的各个参数,并根据其中的主服务器的IP和端口号,检查是否下线。然后向源Sentinel返回一条包含三个参数的Multi Bulk
回复作为SENTINEL is-master-down-by
命令的回复。
-
<down_state>
返回目标Sentinel对主服务器的检查结果,1表示主服务器已下线,0表示主服务器未下线 -
<leader_runid>
可以是*符号或是目标Sentinel的局部领导Sentinel的运行ID -
<leader_eopch>
目标Sentinel的局部领头Sentinel的配置纪元,用于选举领头Sentinel
16.7.3 接受回复
Sentinel会统计其他Sentinel同意主服务器已下线的数量,当这一数量达到配置指定的判断客观下线所需要的数量时,Sentinel会将主服务器实例结构属性的SRI_O_DOWN
标识打开,表示主服务器已经进入客观下线状态。
16.8 选举领头Sentinel
当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个Sentinel会进行协商,选举出一个领头Sentinel,并由领头Sentinel对下线主服务器执行故障转移操作。
Redis选举领头Sentinel的规则和方法:
-
所有在线的Sentinel都有被选为领头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 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将在一段时间之后再次进行选举,直到选出为止。
16.9 故障转移
-
在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器
-
让已下线主服务器属下的所有从服务器都改为复制新的主服务器
-
将已下线主服务器设置为新的主服务器的从服务器
16.9.1 选出新的主服务器
选出一个状态完整、数据完整的从服务器,然后向这个从服务器发送SLAVEOF no one
命令,将从服务器转为主服务器。
-
删除列表里所有下线或是断线的从服务器,保证正常在线
-
删除列表里最近五秒内没有回复过领头Sentinel的INFO命令的从服务器,保证最近成功通信
-
删除所有与已下线服务器连接断开超过
down-after-millseconds*10
ms的从服务器,保证数据较新 -
先选优先级最高,再选复制偏移量最大,再选运行ID最小
发送后,领头Sentinel会以每秒一次的频率向被升级的从服务器发送INFO命令,并观察命令回复中的角色role信息。
16.9.2 修改从服务器的复制目标
向从服务器发送SLAVEOF
命令来实现,让其他从服务器去复制新的主服务器
16.9.3 将旧的主服务器变为从服务器
当server1重新上线时,Sentinel会发送SLAVEOF命令,让它称为server2的从服务器