有读者在网站留言询问:如何进行failover?所以,我稍后会添加这部分。话不多说,走吧!为什么会有哨兵机制?在Redis的主从架构中,由于主从模式是读写分离的,如果主节点(master)挂了,那么就没有主节点来服务客户端的写操作请求,而有将没有主节点的从节点(slave)进行数据同步。如果主节点宕机,如果要恢复服务,需要手动干预,选择一个“从节点”切换到“主节点”,然后让其他从节点指向新的主节点,并且还需要通知上游连接Redis的主节点,更新其配置中主节点的IP地址为“新主节点”的IP地址。这还不算太“聪明”。如果有一个节点可以监控“主节点”的状态,当它发现主节点宕机时,会自动将一个“从节点”切换为“主节点”,这样可以为我们省去很多事情!Redis在2.8版本之后提供的Sentinel机制,用于实现主从节点故障转移。它会监控master节点是否存活,如果发现master节点挂了,会选举一个slave节点切换到master节点,并将新master的相关信息通知slave节点和client节点。哨兵机制如何运作?Sentinel其实就是一个运行在特殊模式下的Redis进程,所以它也是一个节点。从名字“Sentinel”也可以看出,它相当于一个“观察者节点”,观察的对象是主从节点。当然,不仅仅是观察那么简单。当它观察到异常情况时,它会采取一些“行动”来修复异常状态。哨兵节点主要负责三件事:监控、选举和通知。哨兵的职责那么,我们重点学习这三个东西:哨兵节点是如何监控节点的?而如何判断主节点是否真的宕机了呢?根据什么规则选择从节点切换到主节点?如何将新主节点的相关信息通知从节点和客户端?如何判断master节点真的宕机了?sentinel会每隔1秒向所有主从节点发送PING命令。当主从节点收到PING命令后,会向哨兵发送响应命令,让哨兵判断自己是否正常运行。Sentry监控主从节点。如果主节点或从节点在规定的时间内没有响应哨兵的PING命令,哨兵就会将他们标记为“主观下线”。这个“规定时间”是由配置项down-after-milliseconds参数设置的,单位是毫秒。主观下线?线下还有目标吗?是的,没错,客观离线仅适用于主节点。之所以为“主节点”设计“主观下线”和“客观下线”两种状态,是因为有可能“主节点”实际上并没有故障,可能是因为主节点的系统压力节点比较高或者网络发送拥塞导致主节点无法在规定时间内响应哨兵的PING命令。所以为了减少误判的情况,Sentinel在部署的时候不会只部署一个节点,而是将多个节点部署成一个sentinel集群(部署一个sentinel集群至少需要三台机器),通过多个sentinel节点进行判断,可以避免单个sentinel因为自身网络不好而误判master节点下线的情况。同时,多个Sentinels网络同时不稳定的概率很小,一起做决策,也可以降低误判率。具体如何判断主节点“客观下线”?当一个哨兵判断主节点“主观下线”时,它会向其他哨兵发出命令。其他哨兵收到命令后,会根据自身和主节点的网络情况,做出赞成票或拒绝票的响应。.当Sentinel的投票数达到Sentinel配置文件中quorum配置项设置的值时,master节点将被Sentinel标记为“客观下线”。比如有3个Sentinels,quorum配置为2,那么一个Sentinel需要2个赞成票才能将master节点标记为“客观下线”。2个赞成票包括哨兵自己的赞成票和另外两个哨兵的赞成票。PS:quorum的值一般设置为哨兵数量的1/2加1,比如有3个哨兵就设置2。当哨兵判断主节点客观下线后,哨兵会开始从多个“从节点”中选择一个从节点作为新的主节点。哪个Sentinel做master-slavefailover?前面提到,为了更“客观”地判断主节点的故障,一般不会只根据单个sentinel的检测结果来判断,而是多个sentinel一起判断,这样可以减少误判的概率,所以哨兵是基于哨兵集群的方式存在的。问题来了,Sentinel集群中哪个节点进行master-slavefailover?所以这时候也需要在Sentinel集群中选择一个leeder,让leeder进行主从切换。选举Leeder的过程实际上是一个投票过程。在投票开始之前,必须有一个“候选人”。那么谁会成为候选人呢?哪个sentinel节点判断master节点“客观下线”,这个sentinel节点就是一个candidate,所谓的candidate就是一个想要成为Leader的sentinel。例如,假设有三个哨兵。当SentinelB首先判断master节点“主观下线”时,会向其他实例发送is-master-down-by-addr命令。然后,其他哨兵将根据他们与主节点的网络连接,通过投票赞成或拒绝投票来做出回应。当SentinelB收到赞成票数达到Sentinel配置文件中quorum配置项中设置的值时,会将master节点标记为“客观下线”,此时的SentinelB为Leader候选。HowarecandidateselectedasLeader?Candidates向其他Sentinels发送命令,表达自己希望成为Leader进行主从切换,并让所有其他Sentinels进行投票。每个哨兵只有一次投票机会。如果用完,则不能参与投票。它可以为自己或他人投票,但只有候选人可以为自己投票。那么在投票过程中,任何“候选人”都必须满足两个条件:第一,获得半数以上的赞成票;其次,你获得的投票数也必须大于或等于sentinel配置文件中的quorum值。Forexample,supposethereare3sentinelnodesandthequorumissetto2,thenanysentinelwhowantstobecomealeadercanbeelectedaslongashegets2yesvotes.如果不满足条件,则需要重新选举。这时候有同学会问,如果在某个时间点,有两个sentinel节点客观判断master节点下线,那么会有两个候选?此时如何决定谁是Leader?每个候选人先为自己投票,然后向其他Sentinels发起投票请求。如果选民先收到“候选人A”的投票请求,他会先投票给它。如果投票人用尽投票机会,收到“候选人B”的投票请求,则拒绝投票。此时,候选人A首先满足以上两个条件,因此“候选人A”将被选举为leader。为什么至少有3个哨兵节点?如果sentinel集群中只有2个sentinel节点,此时一个sentinel要想成功成为leader,就必须获得2票,而不是1票。因此,如果哨兵集群中有一个哨兵死亡,那么就只剩下一个哨兵了。如果哨兵要成为leader,那么票数不能达到2票,就不能成功成为leader。这个时候是不可能Master-slave节点切换的。因此,通常我们会配置至少3个sentinel节点。这个时候如果哨兵丛中有一个哨兵死亡,那么还剩下两个哨兵。如果这个哨兵要成为leader,此时还有机会达到2票,所以选举还是可以成功的,不会导致无法进行主从节点切换。当然你要问了,如果3个sentinel节点有2个挂了怎么办?这个时候,人类就得介入,或者多加一点哨兵节点。还有一个问题,Redis1master4slave,5sentinel,quorum设置为3,如果2个sentinel失效,当master节点宕机时,sentinel能否判断master节点“客观下线”?主从可以自动切换吗?Sentinel集群可以判断主节点“客观离线”。哨兵集群中还剩下3个哨兵。当一个哨兵判断主节点“主观下线”,向其他2个哨兵询问时,有可能获得3票赞成。这个时候就已经达到quorum的值了。因此,Sentinel集群可以判断master节点“客观离线”。Sentinel集群可以完成主从切换。当一个Sentinel将master节点标记为“客观下线”时,就会进行选举Leader的过程,因为Sentinel集群中还剩下3个Sentinel,那么仍然可以获得一半以上(5/2+1=3)票数,也达到quorum值,满足选举leader的两个条件,所以才能选举成功,这样sentinel集群才能完成主从切换。如果quorum设置为2且3个哨兵失败。此时sentinel集群仍然可以判断master节点“客观下线”,但是sentinel无法完成主从切换,可以自行推导。如果quorum设置为3,如果有3个sentinel失效,则sentinel集群无法判断master节点“客观下线”,也无法完成主从切换。可以看出,当quorum为2时,如果有3个sentinel失效,虽然master节点可以判断为“客观下线”,但是无法完成主从切换。这就像不劳而获。在这种情况下,最好不要这样做。当quorum为3时,可以避免这种无用的工作。所以quorum的值建议设置为sentinel数的一半加1,比如3个sentinel设置2,5个sentinel设置3,sentinel节点数应该是奇数。master-slavefailover的过程是怎样的?在Sentinel集群中通过投票选出sentinelleader后,就可以进行主从故障切换过程,如下图所示:主从故障切换操作包括以下四个步骤:第一步:在离线的masterFrom节点(旧主节点)下的所有“从节点”,选择一个从节点,将其转换为主节点。第二步:让离线主节点下的所有“从节点”修改复制目标,修改为复制“新主节点”;第三步:通过“发布者/订阅者机制”通知将新主节点的IP地址和信息传递给客户端;第四步:继续监控老主节点,当老主节点再次上线时,将其设置为新主节点的从节点;第一步:选择新的主节点故障转移操作第一步是从离线主节点下的所有“从节点”中选择一个状态良好且数据完整的从节点,然后向这个“从节点”发送SLAVEOFnoone命令节点”来设置这个“从节点”转换为“主节点”。这么多“从节点”,应该选择哪个从节点作为新的主节点呢?随机方式好吗?随机方式实现起来非常简单,但是如果选择一个网络状态不好的从节点作为新的主节点,那么在不久的将来可能还需要进行一次主从故障迁移。因此,我们首先要过滤掉网络状态不好的从节点。先过滤掉掉线的从节点,再过滤掉过去网络连接状态不好的从节点。如何判断从节点之前的网络连接状态不好呢?Redis有个配置项叫down-after-milliseconds*10,它的down-after-milliseconds就是主从节点断开连接的最大连接超时时间。如果在down-after-milliseconds毫秒内,主从节点没有通过网络连接,我们可以认为主从节点断开了。如果掉线次数超过10次,说明从节点网络状况不好,不适合做新的主节点。至此,我们已经过滤掉了网络状态不好的从节点,接下来我们将对所有从节点进行三轮检查:优先级、复制进度、ID号。在进行每一轮调查时,谁先获胜的从节点将被选为新的主节点。第一轮检查:哨兵会先按照slave节点的优先级排序,优先级越低,排名越高,第二轮检查:如果优先级相同,检查复制的下标,哪个slave“主节点”如果收到的复制数据多了,先到哪一个。第三轮考察:如果优先级和下标相同,则选择从节点ID较小的。第一轮调查:优先级最高的从节点获胜。Redis有一个配置项叫做slave-priority,可以为slave节点设置优先级。每个从节点的服务器配置不一定相同,我们可以根据服务器性能配置设置从节点的优先级。例如,如果“A从节点”的物理内存是所有从节点中最大的,那么我们就可以将“A从节点”的优先级设置为最高。这样sentinel在进行第一轮考虑时,优先级最高的A从节点将首先获胜,然后成为新的主节点。第二轮调查:复制进度最高的从节点获胜。如果在第一轮检查中发现有两个优先级最高的从节点,则进行第二轮检查,比较这两个从节点的复制进度。.复制进度如何?在主从架构中,主节点会将写操作同步到从节点。在这个过程中,主节点会使用master_repl_offset记录repl_backlog_buffer中最近一次写操作的位置(如下图“主服务器写入的数据”),从节点会使用slave_repl_offset的值记录当前的复制进度(下图中“从服务器读取的位置”的位置)。如果一个slave节点的slave_repl_offset与master_repl_offset最接近,说明它的复制进度最先进,可以选为新的master节点。第三轮检验:ID号较小的从节点获胜。如果在第二轮检查中发现有两个从节点具有相同的优先级和复制进度,则进行第三轮检查比较这两个从节点。ID号小的从节点获胜。什么是身份证号码?每个从节点都有一个编号,就是ID号,用来唯一标识从节点。至此,选主的事情总算是结束了。给大家简单总结一下:slave节点选举出来后,sentinelleader向选中的slave节点发送SLAVEOFnoone命令,让slave节点解除slave节点的状态,成为新的master节点。如下图所示,sentinelleader向选中的从节点server2发送SLAVEOFnoone命令,将从节点升级为新的主节点。发送SLAVEOFnoone命令后,sentinelleader会每秒向升级后的slave节点发送一次INFO命令(故障转移前,INFO命令的频率为每十秒一次),并观察命令回复。角色信息,当被升级节点的角色信息由原来的slave变为master时,sentinelleader就知道被选中的slave节点已经成功升级为master节点。如下图所示,选中的从节点server2已经升级为新的主节点:步骤2:将从节点指向新的主节点。所有“从节点”都指向“新主节点”。这个动作可以通过向“从节点”发送SLAVEOF命令来实现。如下图所示,sentinelleader向所有从节点(server3和server4)发送SLAVEOF,使他们成为新主节点的从节点。所有slave节点指向新的master节点后的拓扑图如下:第三步:通知客户master节点已更换经过前面一系列的操作,sentinel集群终于完成了主从切换,那么如何将新主节点的信息通知客户端呢?这主要是通过Redis的发布者/订阅者机制来实现的。每个哨兵节点都提供了发布/订阅机制,客户端可以订阅来自哨兵的消息。Sentinel提供了多种消息订阅渠道。在主从节点切换过程中,不同的通道包含不同的关键事件。几个常见的事件如下:客户端与Sentinel建立连接后,客户端会订阅Sentinel提供的通道。主从切换完成后,Sentinel会将新主节点的IP地址和端口信息发布到+switch-master通道。这时候,客户端就可以收到这个信息,然后使用这里新的主节点的IP地址与端口进行通信。通过发布者/订阅者机制,有了这些事件通知,客户端不仅可以得到主从切换后新主节点的连接信息,还可以监听到主从切换过程中发生的各种重要事件。这样客户端就可以知道主从切换进行到哪一步了,有助于了解切换的进度。第四步:将旧的主节点变成从节点故障转移操作。最后要做的就是继续监控旧的主节点。当旧的主节点重新上线后,哨兵集群会向其发送SLAVEOF命令,使其成为新的主节点从节点,如下图所示:至此,整个主从节点的故障转移工作为超过。Sentinel集群是如何形成的?前面提到了Redis的发布者/订阅者机制,所以不得不提一下sentinel集群的构成,因为它也是用到了这个技术。刚开始搭建sentinel集群的时候,我当时很惊讶。因为在配置Sentinel信息的时候,只需要填写以下参数,设置master节点的名称,master节点的IP地址和端口号,以及quorum值。sentinelmonitor
