一、前言
首先在之前的文章中介绍了Redis的主从复制原理,但是他有个致命的缺陷,又如何解决呢?这里就引出这篇文章讨论的话题——Redis的哨兵模式。当然在这篇文章中主要介绍哨兵模式的主要的命令、算法原理、面试常问的问题等做个总结。方便博主以后的复习,也希望对各位小伙伴有所帮助。
二、关于哨兵
1、原理
哨兵是一种特殊的模式,Redis提供了哨兵的命令,把哨兵作为一个独立的进程,它能独立运行。其原理是如果master主机故障后,哨兵通过投票数自动发送命令,将某一个slave转换为master,继续对外服务。一般建议哨兵采取奇数台,防止一台sentinel无法连接到master导致切换。
2、作用
①:监控redis的运行状态,包括master与slave.
②:当master故障或者宕机后,能自动将slave切换成master.
三、常用指令
①:sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel:哨兵
monitor:监控
<master-name> <ip> <redis-port>:master的名称、ip地址、对应redis的端口号
quorum:(投票数)表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数。
②:sentinel auth-pass<matser-name> <password>
如果设置了密码,连接master服务器的密码
③:其他
四、一主二从三哨兵模式
一主二从:前面的文章讲了一台master,两台slave,用于数据的读取与存放。
三个哨兵:自动监护和监控集群,不存放数据,只是吹哨人。(所以sentinel配置文件和redis配置文件是完全不一样的)
如图所示:我们采用一主二从三哨兵的模式讲解,图中三个sentinel形成一个集群,我们可以看出sentinel除了监控redis服务器(master,slave1,slave2),也会监控其他的sentinel。哨兵在监控master的时候会出现以下情况:
1、常见问题
①:master宕机后,两台从机的数据是否存在?
答:存在。
②:之前的宕机的master重新启动回来,会不会双master冲突?
答:不会,后面会解释。
2、主观下线(Subjectively Down)
简称SDOWN,是指单个Sentinel实例对服务器做出下线判断。那它是怎么判断的呢?
首先redis的sentinel.conf的配置文件中存在这样一条指令:
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
即在默认的30秒后,单个sentinel可能接受不到订阅(之前讲的发布订阅模型)、网络之间的不通等等原因,即服务器在【sentinel down-after-milliseconds】给定的毫秒数之内没有回复PING或者报错消息,sentinel就会主观上(单方面)认为主节点(master)下线了,master进入了失效(SDOWN)的状态。
3、客观下线(Objectively Down)
简称OSOWN,是指需要一定数量的sentinel,多个哨兵达成一致意见才能认为一个master客观上已经宕机。那它是怎样让多个哨兵达成一致意见的呢?
这是redis的sentinel.conf配置文件关于quorum的解释:
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
其实,在我们配置哨兵的指令里面有一个quorum参数,这个参数是我们进行客观下线的一个重要依据。其所表示的意思是至少有quorum个sentinel认为这个master故障,才会对这个master进行故障转移。之所以这样做的原因是,有时候单个sentinel对master的主观下线,可能只是某个sentinel个人因为网络原因才造成无法连接到master,而master本身却没有问题,有多个sentinel的共同确认。保证了我们这个操作的公平和高效性。
4、挑选兵王(leader)
在我们正常的master宕机后,sentinel们会对这个master是否宕机做出判断,但是谁来做这个故障转移(failover)呢?,是三个sentinel都来做吗?
其实,在我们sentinel.conf文件中规定了:当sentinel对出故障的master做出判断后,各个sentinel会进行协商,即选出一个哨兵中的leader(兵王),即让该leader进行failover(选出新的master)。
当然选出兵王的过程用的是Raft算法,这里可以做一个简单的介绍。
Raft算法
首先我们要了解,在Raft算法中的一些参数,
服务器所处状态:每个服务器都处于leader、follower、candidate这三状态之一;
任期:Raft把时间分割为任意长度的任期(term),term一般用连续的整数标记。
服务器间的通信:
①:RequestVote RPC(请求投票):由candidate在选举期间发起;
②:Append Entries RPC(追加条目):由leader发起,用来复制日志和提供一种心跳机制。
领导者选举实现:
首先Raft算法中具有一种心跳机制,如果此时leader存在,那么它就会定期的向其他follow发送心跳信息,来告诉其他follow我现在是leader,就如图中S1向S2、S3、S4、S5发送消息。如果有一个follow在一段时间类没有收到心跳,那么它就会认为系统中没有leader,那么它就会开始一次选票。在选票期间,follow先将当前term加一,并将状态从follow转为candidate。然后投票给自己,并且并行的向集群中其他服务器发送RequestVote RPC(请求投票)。如果其他服务器当前term值比candidate的term值小,就会投它一票,反之,不会投票给它。
那么最终candidate的选取结果有如下三种(赢、输、无结果):
①:它获得超过一半的票数,成为新的leader,重新开启心跳机制;
②:其他节点赢得选举,candidate收到新leader的心跳,发现新leader的trem>=自己的term,那么candidate就转化状态为follow;
③:一段时间内没有任何获胜者,即集群中有多个candidate,得票太过分散,导致没有任何一个candidate得票数超过一半。此时因为没有新leader产生,会快速进入到下一个选举阶段。
注:这里这是Raft算法的一般介绍,实际中Raft算法的运用和出现的其他情况远不止于此。
5、选举master(重点)
在我们的master宕机后,要在剩余的两个slave中选举新的master,那么到底是那个slave来成为新的饿master呢,这里就会涉及slave转化为新master的算法与步骤。
①:选master
剩余节点健康的情况下,选出新master的规则的流程图:
如图所示:我们以我们的一主二从三哨兵的模式为例,此时master宕机,在slave1与slave2中,我们先比较谁的优先级大,谁就成为新的master;若二者优先级相同,比较谁的复制数据偏移量大,谁成为新的master;若二者复制数据偏移量也相同,则根据Run ID谁小选择谁。
Priority:在redis.conf文件中,优先级slave-priority或者replica-priority最高的从节点是根据数字越小优先级越高的规则来决定的。
replication offset:复制偏移位置的offset最大的从节点。如在slave1与slave2中,slave1之前宕机了,而master与slave2一直存在(即一直进行数据的读取),则当slave1再次恢复过来时,与slave2的replication offset是有区别的,此时master宕机,slave1与slave2的priotity又相同则会选slave2为新的master.
Run ID:在每个redis服务器启动时,会生成一个Run ID。
②:成master
当我们选出作为master的slave后,我们选出的sentinel-leader(兵王)执行slaveof on one操作,将其提升为master节点。随后sentinel-leader(兵王)向其他slave发送指令,使其他slave成为新的master的slave。
③:改旧master
如果此时宕机的旧master重新回来了,我们的sentinel-leader(兵王)会让原来的旧master降级为新master的slave节点恢复正常工作。
总结:所以从以上的描述中,我们可以清晰的明白了sentinel是如何处理failover的,全程由sentinel自动完成,完全不需要人工干预,正好解决了我们Redis主从复制的缺点。
五、哨兵的使用建议
①:哨兵节点数量应该多个,哨兵本身是集群,要保证 高可用性。
②:哨兵节点的个数应该为奇数。
③:各个哨兵的配置文件应该相同。
④:哨兵集群+主从复制,并不能保证数据的丢失。
六、总结
这篇关于Redis哨兵的博客,博主觉得把哨兵的一些基本原理和面试常考点是解释清楚了的。当然博主也花了很多时间来学习和书写博客,如果屏幕前的小伙伴觉得对你有所帮助,不要吝啬你的点赞👍,支持博主哦~