哨兵 - 高可用
哨兵(Sentinel) 是 Redis 的高可用性解决方案:由一个或多个 Sentinel 实例组成的 Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器。
Sentinel 可以在被监视的主服务器进入下线状态时,自动将下线主服务器的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
Sentinel 的作用总结:
- 监控
- 故障转移: Redis Master 下线时, 自动选举新的 Master
- 通知: 使用 Sentinel 时, 客户端通过 Sentinel 获得 Redis 服务器地址, Sentinel 会自动通知最新的 Master 连接信息给客户端;
检查主观下线状态
默认情况下,Sentinel 会以每秒一次的频率向所有与它创建了连接的实例(包括主服务器、从服务器、其他 Sentinel 在内的所有机器)发送 PING 命令来判断实例是否在线。
如果一个实例在 down-after-miliseconds 毫秒内,连续向 Sentinel 返回无效回复,那么 Sentinel 会标记这个实例已经进入主观下线状态。
检查客观下线状态
当 Sentinel 将一个主服务器判断为主观下线之后,为了确定这个主服务器是否真的下线了,它会向同样监视这一服务器的其他 Sentinel 进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。
当 Sentinel 从其他 Sentinel 那里接收到 quorum 个已下线判断之后,Sentinel 就会将服务器置为客观下线,在 flags 上打上 SRI_O_DOWN 标识,并对主服务器执行故障转移操作。
对于每个 Redis 结点, quorum 是独立配置的; 不同的结点 quorum 可以不同;
故障转移
当哨兵监测到某个主节点客观下线之后 (从节点下线不会干啥) ,就会开始故障转移流程。核心流程如下:
-
发起一次选举,选举出领头 Sentinel, 由领头哨兵去触发故障转移;
-
需要超过半数个的哨兵授权, 才能真正进行故障转移; 并且, Sentinel 结点的数量是固定的, 假设本来有 5 个 Sentinel结点, 现在有三个掉线了, 那么永远都无法获得超过半数的授权, 永远都无法故障转移;
-
根据 Redis 官方文档, quorum 仅用来判断客观下线状态, 如果要执行故障转移, 需要超过半数的 Sentinel 结点投票同意; 这也是为什么建议 Sentinel 结点数量 >= 3; 后面会再详细介绍这个问题;
-
领头 Sentinel 在已下线主服务器的所有从服务器里面,选举一个从服务器,并将其升级为新的主服务器, 会将新的配置写到配置文件里。
- slave 结点会有优先级配置, 越小优先级越高, 0 代表没有被选举权
- 优先级相同, 选主从同步的 offset 最大的(说明和上一任主机最接近)
- 还相同, 选 id 小的;
-
领头 Sentinel 将剩余的所有从服务器改为复制新的主服务器, 会将这个配置写到配置文件里。
-
领头 Sentinel 更新相关配置信息,当这个旧的主服务器重新上线时,将其设置为新的主服务器的从服务器。
选举新主节点的方法和选举领头 Sentinel 的方法非常相似,两者都是基于 Raft 算法的领头选举(leader election)方法来实现的。
Raft, 总结一句话 : 少数服从多数, 先到先得;
至少3个哨兵
图中, M是主节点, R是从节点, S是哨兵, C是客户端; quorum 配置为 1;
如果M1和S1下线, 那么剩下的一个哨兵有权判断客观下线, 但无权执行故障转移(因为要超过半数同意);
并且, 如果只是两台机器之间的通信断开, 并未真正下线, 那么两边都可以认为自己是主机, 所以不要这样做;
脑裂问题
脑裂是指哨兵系统中的一个主节点没有下线, 只是和从节点之间的网络断开了, 从节点被选举为新的主节点, 从而出现了多个主节点;
M1和从节点的连接断开后(没有下线), S2 和 S3 有权做故障转移, 假设M2被选举为主节点; 同时C1在往M1写入新的数据;
M1和其余两个结点的连接重新建立后, M1被设置为M2的从节点, 进行主从复制(会先清空M1原本的数据), 造成M1的数据丢失
预防数据丢失:
min-replicas-to-write 1
min-replicas-max-lag 10
当一个主节点(例如上例中的M1) 超过 max-lag 秒无法写入至少 1 个从节点时, 他将拒绝接收客户端新的写入请求;
但是, 这样又有新的问题, 如果是所有从节点下线了, 主节点就会停止工作, 即使主节点可以单机正常工作;
所以, Sentinel 并没有完全解决脑裂问题; 是一种权衡, 在可用性, 数据一致性上的权衡;