当前位置: 首页 > 科技观察

Redis高可用:你把这个叫做Sentinel哨兵集群原理

时间:2023-03-12 16:32:53 科技观察

总结我们知道“主从复制是高可用的基石”。如果从库宕机了,仍然可以向主库或者其他从库发送请求,但是主库宕机了。机器只能响应读操作,不能再执行写请求。因此,主从复制架构面临着一个严重的问题。主库宕机,无法进行“写操作”,无法自动选择一个Slave切换到Master,即无法自动failover。和闺蜜深夜...(此处省略10000字),突然关机,提不起裤从床上爬起来手动切换主从,然后通知其他程序员改地址到新的主库并上线。这么一折腾,我已经从女朋友变成了前男友,我是绝对做不到的。所以我们必须有一个高可用的解决方案。为此,Redis官方提供了一个高可用的解决方案——Sentinel。RedisSentinelCluster原理开篇寄语技术的迭代很快,但是从技术中积累的思想是有益于人生的。所以不要担心中年危机,那些担心中年危机的人通常都很难成长。只要我们长大了,只要我们的认知不断突破,就不用担心中年危机。世界总是需要那些杰出的人才。什么是哨兵(Sentinel)》65哥:码哥,虽然我没有女朋友,但是想掌握这个哨兵模式,防止和女朋友深夜被打扰。说说实现原理《Sentinel》的搭建实例使用三个哨兵组成集群,三个数据节点(一主二从)搭建,如下图所示:Redissentinelcluster哨兵集群搭建的演示这里不再赘述,需要的读者朋友可以点击左下角“阅读原文”查看。65兄弟,你听说过“武当派”的创始人张三狂吗?Redis主从架构就像武当,当家做主。如果首领死了,就需要从武当七侠中选出一位能人担任首领。这就需要有一个部门,可以监控师父的生死和其他武当弟子的生活状态,可以通过投票从武当弟子中选出一个有能力的人作为新的师父,然后召开新闻发布会,宣布新的师父。向世界信息。这个“部门”就是哨兵。Sentry在选举新的head时会遇到以下问题:如何判断head是真的死了,还有可能是假死;选哪个武当弟子当新掌门?通过新闻发布会将新掌门人的相关信息告知全体武当弟子(奴主)和全武林(客)。哨兵部主要负责监视整个武当,选出新掌门,通知整个武当,整个武林的任务。sentinel机制的主要任务Sentinel是Redis的一种运行模式,专注于监控Redis实例(master节点、slave节点)的运行状态,当master时可以通过一系列机制实现master选择和master节点选择节点失败。从切换到故障转移,保证整个Redis系统的可用性。结合Redis的官方文档:https://redis.io/topics/sentinel,我们可以知道RedisSentinel有以下能力:监控:持续监控master和slave是否处于预期的工作状态。自动切换主库:当Master发生故障时,sentinel启动故障自动恢复过程:从slave中选出一个作为新的master。Notification:让slave执行replicaof与新的master同步;并通知客户端与新的master建立连接。Sentinel也是一个Redis进程,但不对外提供读写服务。通常,Sentinel应该配置为奇数。为什么?且听《字节》慢慢分析。65哥:那神秘部门“哨兵”是如何实现这三个能力的呢?我们先从整体的角度来看Sentinel,简单了解整个运行流程,然后再详细分析每一个任务。先从监控说起……监控哨兵只是武当弟子中的一个特殊部门。默认情况下,Sentinel向所有武当弟子、师傅、哨兵(包括Master、Slave、OtherSentinels(含其他Sentinels)发送PING命令)发送PING命令,如果slave在规定时间内没有响应“Sentinel”的PING命令,则“哨兵”会认为这哥们可能在打嗝,会把他记录为“离线状态”;如果主人在规定时间内没有回应“哨兵”的PING命令,哨兵就会判定主人离线,启动“自动切换主控”进程PING命令的回复有两种情况:有效回复:返回+PONG,-LOADING,-MASTERDOWN中的任意一个;无效回复:有效回复以外的回复,或在规定时间内回复任意回复。65哥:哨兵怎么判断“头”的打嗝?头偷尸怎么办?为了防止头“假死”,“哨兵”设计了两个密码:“subjective注销”和“客观注销”。主观下线哨兵使用PING命令检测主从生命状态。如果是无效回复,则哨兵会将此好友标记为“主观下线”。检测到的是武当小弟,是奴仆的角色。然后直接标注“主观下线”。因为主子还在掌舵,奴婢打嗝对整个武当影响不大。还是可以和外界开会,比武论剑,吃喝辣的……如果检测到主子完了,那么哨兵就不能简单的标记“主观下线”然后开始新主人的选举。因为有误判的可能,大师没有打嗝。一旦启动master切换,后续的master选择、开发大会的通知、slave与新master同步数据所花费的时间都会消耗大量的资源。因此,“哨兵”需要降低误判概率。误判一般发生在集群网络压力大,网络拥塞,或者主库本身压力大的情况下。既然一个人容易误判,那么多人一起投票判断。哨兵机制类似,都是以多个实例组成的集群方式部署,这就是哨兵集群。引入多个sentinel实例一起判断,可以避免单个sentinel因为自身网络不好而误判主库下线。同时,多个Sentinels网络同时不稳定的概率很小,一起做决策,也可以降低误判率。客观下线判断master是否下线。只有一个“哨兵”说了算。只有一半以上的哨兵判断主人已经“主观下线”。这时可以将master标记为“目标下线”。事实上,掌门真的打了嗝,华佗就算重生也无药可救。只有当master被判断为“客观下线”时,才会进一步触发sentinel,开始主从切换过程。客观下线主观下线和客观下线的区别简单来说,主观下线是指sentinel认为节点挂了,而客观下线是指sentinel不仅认为节点挂了,还要和其他sentinel通信达到一定数量的哨兵认为是时候让这家伙打嗝了。这里的“一定数量”是合法数量(Quorum),由sentinel监控配置决定。我解释一下配置:#sentinelmonitor#例子如下:sentinelmonitormymaster127.0.0.163792这个配置项用来通知master节点的sentinel需要监控的:sentinelmonitor:代表监控。mymaster:代表主节点的名称,可以自定义。192.168.11.128:代表监控主节点的ip,6379代表端口。2:法定数,表示只有两个或两个以上的sentinel认为master节点不可用时,才会将master设置为客观下线状态,然后进行failover操作。“客观下线”的标准是当有N个sentinel实例时,必须有N/2+1个实例判断master“主观下线”,才能最终判断master“客观下线”。其实就是一个多半的机制。自动切换主库65兄:既然客观上判断master下线了,那么需要重新选择master。“哨兵”的第二个任务是选择新的主人。需要按照一定的规则,从武当弟子中选出一位实力强大的人物作为新的师傅。师傅选好后,新师傅带着众弟子一起吃喝。按照一定的“过滤条件”+“打分”策略,选出“最强王者”作为领头羊,即在海选中通过一些条件过滤一些“无能者”,然后通过的都是帅哥试镜评分和排名。最高的一个被选为新的主人。如图:新主人不宜选择经常断网的帅哥。你想,即使你成为了master,网络很快也会失效,你又得重新选择一个新的master。这不是笑话吗?你必须排除掉它!筛选条件65哥:筛选条件是什么?从库当前在线,离线的直接丢弃;evaluatethepreviousnetworkconnectionstatusdown-after-milliseconds\*10:如果从库一直与主库断开,并且断开次数超过一定的阈值(10次),我们有理由相信网络状况这个从库的性能不是很好,所以我们可以筛选出这个从库。打分过滤掉不合适的奴隶后,进入打分流程。打分会按照三个规则分三轮打分,规则是:slavepriority,通过slave-priority配置项,为不同的slave库设置不同的优先级(后台有人帮不上忙),而那些具有更高优先级的将被直接提升为新的奴隶。主人负责。slave_repl_offset和master_repl_offset的进度差距(谁的武功越接近上一个master的武功越好),如果相同,则继续下一条规则。其实就是比较slave和oldmaster的复制进度差距;slaverunID,在优先级和复制进度相同的情况下,ID号最小的从库得分最高,将被选为新的主库。(从辈分上看,以runID的创建时间来判断,时间越早越好);通知65哥:为什么要开发布会?换任新主子,这等大事,岂能不告天下。除此之外,其他的奴隶弟子也需要知道新掌门是谁,并且跟着新掌门一起吃喝辣养生。在最后一个任务中,“哨兵”将新“主”的连接信息发送给其他从武当弟子,让从执行replacaof命令与新“主”建立连接,进行数据复制,学习新主人的所有武术。另外,“哨兵”还需要通知整个武林(客户端)新掌门的连接信息,让所有想上门求教的人都能找到新掌门,这样很多事情就可以了交给了新的负责人。决定(将读写请求转移到新的master)。哨兵的主要任务和目标的实现Wang,其他“Sentinel”仍然可以协同工作,完成监控,新首领选举,通知slave,master,以及每一位武者(client)。配置sentinel集群时,sentinel配置中只设置masterIP和监听端口,其他sentinel的连接信息没有配置。Sentinelmonitor哨兵是如何相互认识的?他们如何认识奴隶并监视他们?哪个“哨兵”执行主从切换?带着这些疑问,跟随“码哥字节”追根溯源,深入哨兵集群核心。pub/sub实现哨兵间通信,发现slave65哥:哨兵之间是怎么认识的?哨兵之间可以相互通信,做事,主要得益于Redis的pub/sub发布/订阅机制。sentinel与master建立通信,使用master提供的发布/订阅机制发布自己的信息,比如身高体重,是否单身,IP,端口...master有专门的通道供__sentinel__:hello,用于哨兵之间的消息发布和订阅。这就像__sentinel__:hello微信群。哨兵通过主人建立的微信群发布自己的消息,同时关注其他哨兵发布的消息。Redispub/sub机制当多个哨兵实例对主库进行了发布和订阅操作后,它们可以知道彼此的IP地址和端口,从而发现并建立彼此的连接。Redis通过通道单独管理消息。这里的频道其实是不同的微信群。比如“Codege字节阅读器技术群”就是一个致力于技术分享的群。小伙伴们可以关注公众号,后台回复“加群”,一起成长。65哥:哨兵虽然建立了连接,但是还是需要和slave建立连接,不然无法被监控。如何认识奴隶并监督他们?确实,哨兵之间建立连接形成集群是不够的,还需要和slave建立连接,否则无法监听,无法进行主从库的心跳判断。另外,如果发生主从切换,必须通知slave与新的master重新建立连接,进行数据同步。主从架构中数据同步的原理可以移到《Redis 高可用篇:你管这叫主从架构数据一致性同步》。关键是要用master来实现。sentinel向master发送INFO命令。师父自然认识他门下的所有药师。所以master收到命令后,就把slave的列表告诉sentinel。sentinel根据master回复的slave列表信息与各个slave建立连接,并根据这个连接持续监控sentinel。如图所示,Sentinel2向Master发送INFO命令,Master返回slave列表给Sentinel2,Sentinel2根据slave列表的连接信息与各个slave建立连接,实现持续监控基于此连接。其余哨兵也以此为基础进行监控。INFO命令获取slave信息,选择sentinel进行主从切换65兄弟:master打嗝后,sentinel那么多,那么应该用哪个sentinel来进行新的master切换呢?这类似于sentinel判断master“客观下线”,通过投票选出。任意哨兵判断master“主观下线”后,会向其他哨兵好友发送is-master-down-by-addr命令,好友会根据自己与master的连接状态回复Y或N.Y表示是,N表示否。如果一个哨兵得到大多数哨兵的“赞成票”,它就可以将主人标记为“客观下线”。赞成票数由sentinel配置文件中的quorum配置项设置。sentinelmonitor比如一共有3个sentinel组成一个集群,那么quorum可以配置为2,当一个sentinel获得2票赞成时,可以标记为“客观”线”,当然这个投票包括你自己的投票。获得多数票的Sentinel可以向其他Sentinel发送命令,声明它要进行主从切换。并让其他sentinel投票,投票这个过程叫做“Leader选举”,要成为“Leader”可没那么简单,得有两把刷子,需要满足以下条件:获得其他哨兵好友半数以上的赞成票;数量offavorablevotes必须大于等于配置文件quorum的值,如果sentinel集群中有2个instance,此时如果一个sentinel想要成为leader,必须得到2票,而不是1票。因此,如果一个sentinel挂了,那么此时的集群就无法perform主从库切换。因此,通常我们至少配置3个Sentinel实例。这也是哨兵集群部署奇数,偶数冗余的原因。选举过程如下图所示:RedisSentinel实现主从切换,通过pub/sub实现客户端事件通知当媒体报道传播开来,感兴趣的人自然会关注并订阅相关事件,并根据事件。Redis中也类似,通过pub/sub机制发布不同的事件,客户端可以在这里订阅消息。客户端可以订阅Sentinel的消息。Sentinel提供了多种消息订阅通道,不同的通道在主从库切换过程中包含不同的关键事件。即在不同的“微信群”中发布不同的活动,让对活动感兴趣的人进群。masterofflineevent+sdown:进入“主观下线”状态;-sdown:退出“主观下线”状态;+odown:进入“目标离线”状态;-odown:退出“目标离线”状态;配置事件+slave-reconf-sent:sentinel发送replicaof命令重新配置从库;+slave-reconf-inprog:slave配置新的master,但还没有同步;+slave-reconf-done:slave配置新的master,并完成与新master的数据同步;新主库switch+switch-master:master的地址变了。了解这些渠道后,客户可以订阅来自Sentry的消息。客户端读取Sentinel的配置文件后,可以获得Sentinel的地址和端口,并与Sentinel建立网络连接。然后,我们可以在客户端执行订阅命令来获取不同的事件消息。举个栗子:下面的命令订阅“所有实例进入目标下线状态的事件”SUBSCRIBE+odown注意事项及配置说明你找到了吗?Redis的pub/sub发布订阅机制尤为重要。通过pub/sub机制,可以在Sentinels之间、Sentinels和从库之间、Sentinels和client之间建立sentinel和Connection,各种事件的发布也是通过这个机制实现的。down-after-millisecondsSentinel配置文件中的down-after-milliseconds选项指定了Sentinel主观判断实例下线所需的时长:如果实例在down-after-milliseconds毫秒内连续向Sentinel返回无效回复,那么Sentinel会修改这个instance对应的数据,表示这个instance已经进入主观下线状态。需要保证所有sentinel实例的配置一致,尤其是down-after-milliseconds的主观下线判断值。因为这个值在不同的Sentinel实例上配置不一致,导致Sentinel集群对故障主库没有达成共识,没有及时切换主库。最后的结果就是集群服务不稳定。down-after-milliseconds*10down-after-milliseconds是我们认为主从数据库断开连接的最大连接超时时间。如果在down-after-milliseconds毫秒内,主从节点没有通过网络连接,我们可以认为主从节点断开了。如果断线次数超过10次,说明从库网络状况不好,不适合作为新的主库使用。总结哨兵的主要任务Redis哨兵机制是实现Redis服务不间断的高可用手段之一。主从架构集群的数据同步是数据可靠性的基本保证;主库宕机,自动主从切换是不间断服务的关键支撑。Redis哨兵机制实现主从库自动切换,和闺蜜在一起再也不怕master挂了:监控主从运行状态,客观判断是否正常离线;master客观下线后,选择一台Slave切换到master;通知slave和client新的master信息。sentinel集群的原理是为了避免单个sentinel失效后主从切换,降低误判率,引入了sentinel集群;sentinel集群需要一些机制来支持它的正常运行:基于pub/sub机制实现sentinel集群之间的通信;根据INFO命令获取slave列表,帮助sentinel与slave建立连接;通过哨兵的pub/sub,实现客户端与哨兵之间的事件通知。主从切换不是通过随机选择一个sentinel来进行的,而是通过投票仲裁,选出一个Leader,由Leader负责主从切换。