此时我们再去查看配置文件,也多了两行发现的哨兵id:
sentinel-26379.conf 的配置为
port 26379 dir "/root/redis-6.0.8/data" sentinel myid d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 sentinel deny-scripts-reconfig yes sentinel monitor tmlmaster 127.0.0.1 6379 2 sentinel config-epoch tmlmaster 0 # Generated by CONFIG REWRITE protected-mode no user default on nopass ~* +@all sentinel leader-epoch tmlmaster 0 sentinel known-replica tmlmaster 127.0.0.1 6380 sentinel known-replica tmlmaster 127.0.0.1 6381 sentinel known-sentinel tmlmaster 127.0.0.1 26381 2adb9e95cee7937e77dc42eb018504d94c7ed433 sentinel known-sentinel tmlmaster 127.0.0.1 26380 f1b5da2c58c4c45929178484718230114bdf090a sentinel current-epoch 0
sentinel-26380conf 的配置为
port 26380 dir "/root/redis-6.0.8/data" sentinel myid f1b5da2c58c4c45929178484718230114bdf090a sentinel deny-scripts-reconfig yes sentinel monitor tmlmaster 127.0.0.1 6379 2 sentinel config-epoch tmlmaster 0 # Generated by CONFIG REWRITE protected-mode no user default on nopass ~* +@all sentinel leader-epoch tmlmaster 0 sentinel known-replica tmlmaster 127.0.0.1 6380 sentinel known-replica tmlmaster 127.0.0.1 6381 sentinel known-sentinel tmlmaster 127.0.0.1 26381 2adb9e95cee7937e77dc42eb018504d94c7ed433 sentinel known-sentinel tmlmaster 127.0.0.1 26379 d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 sentinel current-epoch 0
sentinel-26381conf 的配置为
port 26381 dir "/root/redis-6.0.8/data" sentinel myid 2adb9e95cee7937e77dc42eb018504d94c7ed433 sentinel deny-scripts-reconfig yes sentinel monitor tmlmaster 127.0.0.1 6379 2 sentinel config-epoch tmlmaster 0 # Generated by CONFIG REWRITE protected-mode no user default on nopass ~* +@all sentinel leader-epoch tmlmaster 0 sentinel known-replica tmlmaster 127.0.0.1 6380 sentinel known-replica tmlmaster 127.0.0.1 6381 sentinel known-sentinel tmlmaster 127.0.0.1 26379 d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 sentinel known-sentinel tmlmaster 127.0.0.1 26380 f1b5da2c58c4c45929178484718230114bdf090a sentinel current-epoch 0
也就是说,监控同一主master的服务器,不仅会发现其从服务器还会发现彼此具有同一监听任务的哨兵
查看主从工作状态
主从模式搭建好我们首先看下能不能正常玩儿,我们先从主的客户端塞条数据进去,然后从从客户端取数据看能不能取到,往主里set数据
[root@192 redis-6.0.8]# redis-cli -p 6379 127.0.0.1:6379> set mylove guochengyu OK 127.0.0.1:6379>
从从机get数据:
[root@192 ~]# cd redis-6.0.8 [root@192 redis-6.0.8]# redis-cli -p 6380 127.0.0.1:6380> get mylove "guochengyu" 127.0.0.1:6380>
说明主从架构是完好的,接下来我们测验下哨兵如何选举和切换
宕机主查看哨兵工作
首先我们停掉主的服务器来查看,我们先停掉主服务器:
67863:M 01 Nov 2020 16:28:23.148 * Synchronization with replica 127.0.0.1:6381 succeeded ^C67863:signal-handler (1604220955) Received SIGINT scheduling shutdown... 67863:M 01 Nov 2020 16:55:55.524 # User requested shutdown... 67863:M 01 Nov 2020 16:55:55.524 * Calling fsync() on the AOF file. 67863:M 01 Nov 2020 16:55:55.524 * Saving the final RDB snapshot before exiting. 67863:M 01 Nov 2020 16:55:55.524 * DB saved on disk 67863:M 01 Nov 2020 16:55:55.524 # Redis is now ready to exit, bye bye... [root@192 config]#
查看哨兵打出来的服务日志:
68018:X 01 Nov 2020 16:56:25.582 # +sdown master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.683 # +odown master tmlmaster 127.0.0.1 6379 #quorum 2/2 68018:X 01 Nov 2020 16:56:25.683 # +new-epoch 1 68018:X 01 Nov 2020 16:56:25.683 # +try-failover master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.684 # +vote-for-leader d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 1 68018:X 01 Nov 2020 16:56:25.686 # f1b5da2c58c4c45929178484718230114bdf090a voted for d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 1 68018:X 01 Nov 2020 16:56:25.686 # 2adb9e95cee7937e77dc42eb018504d94c7ed433 voted for d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 1 68018:X 01 Nov 2020 16:56:25.786 # +elected-leader master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.786 # +failover-state-select-slave master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.848 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.849 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:25.925 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:26.788 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:26.788 # +failover-state-reconf-slaves master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:26.864 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:27.826 # -odown master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:27.827 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:27.827 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:27.898 # +failover-end master tmlmaster 127.0.0.1 6379 68018:X 01 Nov 2020 16:56:27.898 # +switch-master tmlmaster 127.0.0.1 6379 127.0.0.1 6381 68018:X 01 Nov 2020 16:56:27.898 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6381 68018:X 01 Nov 2020 16:56:27.898 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381
可以看到新的主为6381机器,接下来把6379和6380连接到6381上,然后因为6379掉线,就踢掉6379。
哨兵模式工作原理
我们知道哨兵的三个工作顺序是三个阶段:监控阶段-通知阶段-故障转移阶段
监控阶段
监听阶段主要就是建立一个监听频道:
详细流程如下,一个哨兵在连接master后会记录哨兵状态,同时master也会记录哨兵,接下来哨兵观察是否有其它哨兵,如果有连接到其它哨兵并同步状态,然后会同步获取slave的状态,最终哨兵之间组成网络,互相同步消息。
通知阶段
这个阶段是维护一个长期信息对等的阶段,每个哨兵会将自己获取到的信息同步给其它哨兵。
故障转移阶段
这部分需要分为三个阶段,确定master宕机,选举哨兵leader,哨兵leader选择新master,主从切换:
判定master宕机
如果其中一个哨兵认为master挂了**【主观下线】,会将信息在哨兵集群中进行同步,此时其它哨兵会去检测master是否确实挂了,如果超过半数以上哨兵认为master挂了,则该master被认定挂了【客观下线】**:
选举哨兵leader
当认定master客观下线后,就需要进行故障转移,此时需要推举一个哨兵去处理故障转移事项。
这个时候就需要竞选处理故障的哨兵,一个redis服务被判断为客观下线时,多个监视该服务的sentinel协商,选举一个领头sentinel,对该redis服务进行故障转移操作。选举领头sentinel 遵循以下规则:
- 所有的sentinel都有公平被选举成领头的资格。
- 所有的sentinel都有且只有一次将某个sentinel选举成领头的机会(在一轮选举中),一旦选举某个sentinel为领头,不能更改。
- sentinel设置领头sentinel是先到先得,一旦当前sentinel设置了领头sentinel,以后要求设置sentinel为领头请求都会被拒绝。
- 每个发现服务客观下线的sentinel,都会要求其他sentinel将自己设置成领头。
- 当一个sentinel(源sentinel)向另一个sentinel(目sentinel)发送is-master-down-by-addr ip port current_epoch runid命令的时候,runid参数不是*,而是sentinel运行id,就表示源sentinel要求目标sentinel选举其为领头。
- 源sentinel会检查目标sentinel对其要求设置成领头的回复,如果回复的leader_runid和leader_epoch为源sentinel,表示目标sentinel同意将源sentinel设置成领头。
- 如果某个sentinel被半数以上的sentinel设置成领头,那么该sentinel既为领头。
- 如果在限定时间内,没有选举出领头sentinel,暂定一段时间,再选举。
那么该选谁由什么决定呢?
- 每个做主观下线的sentinel节点向其他sentinel节点发送is-master-down-by-addr ip port current_epoch runid命令,要求将它设置为领导者。
- 收到命令的sentinel节点如果还没有同意过其他的sentinel发送的命令(还未投过票),那么就会同意,否则拒绝。
- 如果该sentinel节点发现自己的票数已经过半且达到了quorum的值,就会成为领导者
- 如果这个过程出现多个sentinel成为领导者,则会等待一段时间重新选举。
总结一句话就是谁快速的发出了选举邀请就有大概率被选上,就是先到先得机制
哨兵leader选择新master
哨兵leader处理故障时,首先要选举一个备选master,要pass掉【不在线的、响应慢的、与原master断开时间久的】在进行了这些排除后,执行优先原则:
- 优先级:sentinel首先会根据slaves的优先级来进行排序,优先级越小排名越靠前。
- offset:如果优先级相同,则查看复制的下标,哪个从master接收的复制数据多,哪个就靠前。offset靠后的。
- 进程runid:如果优先级和下标都相同,就选择进程ID较小的那个。
一个redis无论是master还是slave,都必须在配置中指定一个slave优先级
主从切换
一旦选举出了master之后,就需要按如下方式操作进行主从切换:
- 向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。
- 通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。
- 向已下线主服务器的从服务器发送 SLAVEOF 命令, 让它们去复制新的主服务器。
- 当所有从服务器都已经开始复制新的主服务器时, 领头 Sentinel 终止这次故障迁移操作。
以上就是整个故障转移的过程。我们再回去看日志可以看到这些过程:
68411:X 01 Nov 2020 16:56:25.605 # +sdown master tmlmaster 127.0.0.1 6379 68411:X 01 Nov 2020 16:56:25.686 # +new-epoch 1 68411:X 01 Nov 2020 16:56:25.686 # +vote-for-leader d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 1 68411:X 01 Nov 2020 16:56:25.689 # +odown master tmlmaster 127.0.0.1 6379 #quorum 3/2 68411:X 01 Nov 2020 16:56:25.689 # Next failover delay: I will not start a failover before Sun Nov 1 17:02:26 2020 68411:X 01 Nov 2020 16:56:26.864 # +config-update-from sentinel d8a28dddef8b037ba99bd551ac9f0bde8ea5dde3 127.0.0.1 26379 @ tmlmaster 127.0.0.1 6379 68411:X 01 Nov 2020 16:56:26.864 # +switch-master tmlmaster 127.0.0.1 6379 127.0.0.1 6381 68411:X 01 Nov 2020 16:56:26.864 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6381 68411:X 01 Nov 2020 16:56:26.864 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381 68411:X 01 Nov 2020 16:56:56.899 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381
此时我们重新启动master会发现重新连接到了哨兵的监控体系:
68018:X 01 Nov 2020 16:56:27.898 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ tmlmaster 127.0.0.1 6381 68018:X 01 Nov 2020 16:56:27.898 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381 68018:X 01 Nov 2020 16:56:57.923 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381 68018:X 01 Nov 2020 17:34:58.481 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381 68018:X 01 Nov 2020 17:35:08.420 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ tmlmaster 127.0.0.1 6381
昔日的master成为了一个slave连接到了现在的master6381上了。