05-Redis 多机之2 - 哨兵 脑裂
1、原理
1.1、概述
哨兵模式的 redis 集群有三种角色:sentinel/master/slave,它们通过 tcp 链接,相互建立联系。
sentinel 作为高可用集群管理者,它的功能主要是:检查故障,发现故障,故障转移。
1.2、故障转移流程
- 在 redis 集群中,当 sentinel 检测到 master 出现故障,那么 sentinel 需要对集群进行故障转移。
- 当一个 sentinel 发现 master 下线,它会将下线的 master 确认为主观下线。
- 当“法定个数”(quorum)sentinel 已经发现该 master 节点下线,那么 sentinel 会将其确认为客观下线。
- 多个 sentinel 根据一定的逻辑,选举出一个 sentinel 作为 leader,由它去进行故障转移,将原来连接已客观下线 master 最优的一个 slave 提升为新 master 角色。旧 master 如果重新激活,它将被降级为 slave。
1.3、脑裂场景
我们看看下面的部署:两个机器,分别部署了 redis 的三个角色。
如果将集群部署在两个机器上(如下图)。
sentinel 配置
quorum = 1
,也就是一个 sentinel 发现故障,也可以选举自己为 leader,进行故障转移。M:redis 主服务 master
R:redis 副本 replication / slave
S:redis 哨兵 sentinel
C:redis 客户端
1 |
|
因为某种原因,两个机器断开链接,S2 将同机器的 R1 提升角色为 master,这样集群里,出现了两个 master 同时工作 —— 脑裂出现了。不同的 client 链接到不同的 redis 进行读写,那么两台机器就出现了 redis 数据不一致的现象。
1 |
|
2、解决方案
通过合理部署配置 sentinel/master,降低脑裂出现概率。
2.1. sentienl 配置
合理部署 sentinel 的节点个数,以及配置 sentinel 选举的法定人数。
- sentinel 节点个数最好 >= 3。
- sentinel 节点个数最好是基数。
- sentinel 的选举法定人数设置为 ( $frac{n}{2} + 1$ )。
- 配置
1 |
|
- quorum
法定人数
。作用:多个 sentinel 进行相互选举,有超过法定人数
的 sentinel 选举某个 sentinel 为 leader,那么他就成为 leader, leader 负责故障转移。这个法定人数,可以配置,一般是 sentinel 个数一半以上 ( $ \frac{n}{2} + 1 $ ) 比较合理。如果 sentinel 个数总数为 3,那么最好 quorum == 2,这样最接近真实:少数服从多数,不会出现两个票数一样的 leader同时被选上,进行故障转移。
1 |
|
2.2. master 配置
如果 master 因为某些原因与一定数量的副本失去联系了,通过修改 master 配置项,可以禁止 client 向故障的 master 写数据。
2.2.1. 问题
按照上述的 sentinel 部署方案,下面三个机器,任何一个机器出现问题,只要两个 sentinel 能相互链接,故障转移是正常的。
1 |
|
假如 M1 机器与其它机器断开链接了,S2 和 S3 两个 sentinel 能相互链接,sentinel 能正常进行故障转移,sentinel leader 将 R2 提升为新的 master 角色 [M2]。但是客户端 C1 仍然能读写 M1,这样仍然会出现问题,所以我们不得不对 M1 进行限制。
1 |
|
2.2.2、解决方案
限制 M1 比较简单的方案,通过修改 redis 配置 redis.conf
,检查 master 节点与其它副本的联系。当 master 发现它的副本下线或者通信超时的总数量小于阈值时,那么禁止 master 进行写数据。
但是这个方案也不是完美的,
min-slaves-to-write
依赖于副本的链接个数,如果 slave 个数设置不合理,那么集群很难故障转移成功。
2.2.2.1. 配置
- redis.conf
1 |
|
注意:高版本 redis 已经修改这个两个选项
1 |
|
2.2.2.2. 源码实现流程
- 时钟定期检查副本链接健康情况。
1 |
|
- 超出配置范围,master 禁止写命令。
1 |
|
3、小结
- redis 脑裂主要表现为:同一个 redis 集群,原来的 master,经过故障转移后,出现多个 master。
- 解决方案主要通过 sentinel 哨兵的配置和 redis 的配置去解决问题。
- 上述方案也是有不足的地方,例如 redis 配置限制可能会受到副本个数的影响,所以具体设置,要看具体的业务场景。主要是怎么通过比较小的代价去解决问题,或者降低出现问题的概率。
- redis 虽然已经发布了 gossip 协议的无中心集群,sentinel 哨兵模式还是比较常用的,我们不建议直接使用 sentinel,可以考虑使用 codis。