Redis之哨兵
1、什么是哨兵
对于Master宕机后的冷处理方式是无法实现高可用的。Redis从2.6版本开始提供了高可用的解决方案–Sentinel哨兵机制。在集群中再引入一个节点,该节点充当Sentinel哨兵,用于监视Master的运行状态,并在Master宕机后自动指定一个Slave作为新的Master。整个过程无需人工操作,完全由哨兵自动完成。
不过,此时的 Sentinel 哨兵又成为了一个单点故障点:若哨兵发生宕机,整个集群将瘫 痪。所以为了解决 Sentinel 的单点问题,又要为 Sentinel 创建一个集群,即 Sentinel 哨兵集 群。一个哨兵的宕机,将不会影响到 Redis 集群的运行。
那么这些 Sentinel 哨兵是如何工作的呢?Sentinel 是如何知道其监视的 Master 状态的呢?每个Sentinel都会定时向Master发送心跳,如果Master在有效期内向它们都进行了响应,那么就认为Master是活着的。如果Sentinel中有quorum个哨兵没有收到响应,那么就认为Master已经宕机,当然会有一个Sentinel做Failover故障转移。即将原来的某一个Slave晋升为Master。
2、Redis高可用集群搭建
在“不差钱”的情况下,可以让 Sentinel 占用独立的主机,即在 Redis 主机上只启动 Redis 进程,在 Sentinel 主机上只启动 Sentinel 进程。下面要搭建一个“一主二从三哨兵”的高可 用伪集群,即这些角色全部安装运行在一台主机上。“一主二从”使用前面的主从集群,下 面仅搭建一个 Sentinel 伪集群。
角色 | 端口号 | 角色 | 端口号 | |
---|---|---|---|---|
master | 6380 | sentinel | 26380 | |
slave | 6381 | sentinel | 26381 | |
slave | 6382 | sentinel | 26382 |
具体搭建就不记笔记了,网上有很多。
3、哨兵机制原理
3.1、三个定时任务
Sentinel 维护着三个定时任务以监测 Redis 节点及其它 Sentinel 节点的状态。
3.1.1、info任务
每个 Sentinel 节点每 10 秒就会向 Redis 集群中的每个节点发送 info 命令,以获得最新的 Redis 拓扑结构。
3.1.2、心跳任务
每个Sentinel节点每1秒就会向所有Redis节点及其它Sentinel节点发送一条ping命令, 以检测这些节点的存活状态。该任务是判断节点在线状态的重要依据。
3.1.3、发布/订阅任务
每个 Sentinel 节点在启动时都会向所有 Redis 节点订阅_ sentinel _:hello 主题的信息, 当 Redis 节点中该主题的信息发生了变化,就会立即通知到所有订阅者。
启动后,每个 Sentinel 节点每 2 秒就会向每个 Redis 节点发布一条_ sentinel _:hello 主 题的信息,该信息是当前 Sentinel 对每个 Redis 节点在线状态的判断结果及当前 Sentinel 节 点信息。
当 Sentinel 节点接收到_ sentinel _:hello 主题信息后,就会读取并解析这些信息,然后 主要完成以下三项工作:
如果发现有新的 Sentinel 节点加入,则记录下新加入 Sentinel 节点信息,并与其建立连 接。
如果发现有 Sentinel Leader 选举的选票信息,则执行 Leader 选举过程。
汇总其它 Sentinel 节点对当前 Redis 节点在线状态的判断结果,作为 Redis 节点客观下 线的判断依据。
3.2、Redis节点下线判断
对于每个 Redis 节点在线状态的监控是由 Sentinel 完成的。
3.2.1、主观下线
每个Sentinel节点每秒就会向每个Redis节点发送ping心跳检测,如果Sentinel在down-after-milliseconds时间内没有收到某个Redis节点的回复,则Sentinel节点就会对该Redis节点做出“下线状态”的判断。这个判断仅仅是当前Sentinel节点的“一家之言”,所以称为主观下线。
3.2.2、客观下线
当Sentinel主观下线的节点是master时,该Sentinel节点会向每个其他Sentinel节点发送sentinel is-master-down-by-addr 命令,以询问其对master在线状态的判断结果。这些Sentinel节点在收到命令后会向这个发问Sentienl响应0(在线)或1(下线)。当Sentinel收到超过quorum个下线判断后,就会对master做出客观下线判断。
3.3、Sentinel Leader选举
当Sentinel节点对master做出客观下线判断后,会由Sentinel Leader来完成后续的故障转移,即Sentinel集群中的节点也是非对等节点,是存在Leader与Follower的。
Sentinel 集群的 Leader 选举是通过 Raft 算法实现的。简单介绍一下大致思路。
每个选举参与者都具有当选 Leader 的资格,当其完成了“客观下线”判断后,就会立 即“毛遂自荐”推选自己做 Leader,然后将自己的提案发送给所有参与者。其它参与者在收 到提案后,只要自己手中的选票没有投出去,其就会立即通过该提案并将同意结果反馈给提 案者,后续再过来的提案会由于该参与者没有了选票而被拒绝。当提案者收到了同意反馈数 量大于等于 max(quorum,sentinelNum/2+1)时,该提案者当选 Leader。
说明:
在网络没有问题的前提下,基本就是谁先做出了“客观下线”判断,谁就会首先发起 Sentinel Leader 的选举,谁就会得到大多数参与者的支持,谁就会当选 Leader。
Sentinel Leader 选举会在次故障转移发生之前进行。
故障转移结束后 Sentinel 不再维护这种 Leader-Follower 关系,即 Leader 不再存在。 (这里的主要原因是完成Sentinel Leader选举是很块很快的,而且master下线的概率也很低,所以为了节约计算机资源,Leader用完就没了,什么时候需要就什么时候重新选举)
3.4、master选择算法
在进行故障转移时,Sentinel Leader 需要从所有 Redis 的 Slave 节点中选择出新的 Master。 其选择算法为:
- 过滤掉所有主观下线的,或心跳没有响应 Sentinel 的,或 replica-priority 值为 0 的 Redis 节点
- 在剩余 Redis 节点中选择出 replica-priority 最小的的节点列表。如果只有一个节点,则 直接返回,否则,继续
- 从优先级相同的节点列表中选择复制偏移量最大的节点。如果只有一个节点,则直接返 回,否则,继续
- 从复制偏移值量相同的节点列表中选择动态 ID 最小的节点返回
3.5、故障转移过程
Sentinel Leader 负责整个故障转移过程,经历了如上步骤:
- Sentinel Leader 根据 master 选择算法选择出一个 slave 节点作为新的 master
- Sentinel Leader 向新 master 节点发送 slaveof no one 指令,使其晋升为 master
- Sentinel Leader 向新 master 发送 info replication 指令,获取到 master 的动态 ID
- Sentinel Leader 向其余 Redis 节点发送消息,以告知它们新 master 的动态 ID
- Sentinel Leader 向其余 Redis 节点发送 slaveof 指令,使它们成为新 master 的 slave
- Sentinel Leader 从所有 slave 节点中每次选择出 parallel-syncs 个 slave 从新 master 同步数 据,直至所有 slave 全部同步完毕
- 故障转移完毕
3.6、节点上线
3.6.1、原Redis节点上线
无论是原下线的 master 节点还是原下线的 slave 节点,只要是原 Redis 集群中的节点上 线,只需启动 Redis 即可。因为每个 Sentinel 中都保存有原来其监控的所有 Redis 节点列表, Sentinel 会定时查看这些 Redis 节点是否恢复。如果查看到其已经恢复,则会命其从当前 master 进行数据同步。
不过,如果是原 master 上线,在新 master 晋升后 Sentinel Leader 会立即先将原 master 节点更新为 slave,然后才会定时查看其是否恢复。
3.6.2、新Redis节点上线
如果需要在 Redis 集群中添加一个新的节点,其未曾出现在 Redis 集群中,则上线操作 只能手工完成。即添加者在添加之前必须知道当前 master 是谁,然后在新节点启动后运行 slaveof 命令加入集群。
3.6.3、Sentinel节点上线
如果要添加的是 Sentinel 节点,无论其是否曾经出现在 Sentinel 集群中,都需要手工完 成。即添加者在添加之前必须知道当前 master 是谁,然后在配置文件中修改 sentinel monitor 属性,指定要监控的 master。然后启动 Sentinel 即可。