目录
4. leader 挑选出合适的 slave 成为新的 master
一, 主从复制存在的问题
1.1 主从复制存在的问题
Redis 的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作⽤:
- 作为主节点的⼀个备份,⼀旦主节点出了故障不可达的情况,从节点可以作为后备 “顶” 上 来,并且保证数据尽量不丢失(主从复制表现为最终⼀致性);
- 从节点可以分担主节点上的读压⼒,让主节点只承担写请求的处理,将所有的读请求负载均衡到各个从节点上.
但是主从复制模式并不是万能的,它同样遗留下以下几个问题:
- 主节点发生故障时,进行主备切换额的过程是很复杂的,需要完全的人工参与,导致故障恢复时间无法保障;
- 主节点可以将读压力分散出去,但是写压力/存储压力式无法被分担的,还是受到单机的限制.
其中第一个问题是高可用问题,即Redis哨兵主要解决的问题,第二个问题是属于存储分布式的问题,留给Redis集群去解决;这篇博客主要讨论第一个问题.
1.2 如何判断主节点真的故障了
哨兵会每隔 1 秒给所有主从节点发送 PING 命令,当主从节点收到 PING 命令后,会发送一个响应命令给哨兵,这样就可以判断它们是否在正常运行.
1.3 主观下线和客观下线
主观下线
如果主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令,哨兵就会将它们标记为「主观下线」;这个「规定的时间」是配置项 down-after-milliseconds
参数设定的,单位是毫秒.
客观下线
为什么设置客观下线?
之所以针对「主节点」设计「主观下线」和「客观下线」两个状态,是因为有可能「主节点」其实并没有故障,可能只是因为主节点的系统压力比较大或者网络发送了拥塞,导致主节点没有在规定时间内响应哨兵的 PING 命令.
所以,为了减少误判的情况,哨兵在部署的时候不会只部署一个节点,而是用多个节点部署成哨兵集群(最少需要三台机器来部署哨兵集群),通过多个哨兵节点一起判断,就可以就可以避免单个哨兵因为自身网络状况不好,而误判主节点下线的情况;同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低.
如何判断客观下线
当一个哨兵判断主节点为主观下线后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应.
当这个哨兵的赞同票数达到哨兵配置文件中的 quorum 配置项设定的值后,这时主节点就会被该哨兵标记为客观下线;
例如,现在有 3 个哨兵,quorum 配置的是 2,那么一个哨兵需要 2 张赞成票,就可以标记主节点为“客观下线”了。这 2 张赞成票包括哨兵自己的一张赞成票和另外两个哨兵的赞成票.
二, 哨兵机制恢复主节点故障
2.1 人工恢复主节点故障
- 运维⼈员通过监控系统,发现 Redis 主节点故障宕机;
- 运维⼈员从所有节点中,选择⼀个(选择了 slave 1) 执⾏ slaveof no one,使其作为新的主 节点;
- 运维⼈员让剩余从节点(为 slave 2) 执⾏ slaveof {newMasterIp} {newMasterPort} 从新主节点开始数据同步;
- 更新应⽤⽅连接的主节点信息到 {newMasterIp} {newMasterPort};
- 如果原来的主节点恢复,执⾏ slaveof {newMasterIp} {newMasterPort} 让其成为⼀个从节点;
上述过程可以看到基本需要⼈⼯介⼊,⽆法被认为架构是⾼可⽤的,⽽这就是 Redis Sentinel 所要做 的.
2.2 哨兵自动恢复主节点故障
当主节点出现故障时,Redis Sentinel 能⾃动完成故障发现和故障转移,并通知应⽤⽅,从⽽实现真正的⾼可⽤;Redis Sentinel 是⼀个分布式架构,其中包含若⼲个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进⾏监控,当它发现节点不可达时,会对节点做下线表⽰.如果下线的是主节点,它还会和其他的 Sentinel 节点进⾏ “协商”,当⼤多数 Sentinel 节点对主节点不可达这个结论达成共识之后,它们会在内部 “选举” 出⼀个领导节点来完成⾃动故障转移的⼯作,同时将这个变化实时通知给 Redis 应⽤⽅;整个过程是完全⾃动的,不需要⼈⼯介⼊.
整体架构图如图所示:
- Redis Sentinel 相⽐于主从复制模式是多了若⼲(建议保持奇数)Sentinel 节点⽤于实现监控数据节 点,哨兵节点会定期监控所有节点(包含数据节点和其他哨兵节点).针对主节点故障的情况,故障转移流程⼤致如下:
- 主节点故障,从节点同步连接中断,主从复制停⽌;
- 哨兵节点通过定期监控发现主节点出现故障.哨兵节点与其他哨兵节点进⾏协商,达成多数认同主节点故障的共识;这步主要是防⽌该情况:出故障的不是主节点,⽽是发现故障的哨兵节点,该情况经常发⽣于哨兵节点的⽹络被孤⽴的场景下;
- 哨兵节点之间使⽤ Raft 算法选举出⼀个领导⻆⾊,由该节点负责后续的故障转移⼯作;
- 哨兵领导者开始执⾏故障转移:从节点中选择⼀个作为新主节点;让其他从节点同步新主节点;通 知应⽤层转移到新主节点.
通过上⾯的介绍,可以看出 Redis Sentinel 具有以下⼏个功能:
- 监控: Sentinel 节点会定期检测 Redis 数据节点、其余哨兵节点是否可达;
- 故障转移: 实现从节点晋升(promotion)为主节点并维护后续正确的主从关系;
- 通知: Sentinel 节点会将故障转移的结果通知给应⽤⽅.
三, 主从故障转移过程(选举原理)
选举原理
假定当前环境如上⽅介绍, 三个哨兵(sentenal1, sentenal2, sentenal3), ⼀个主节点(redis-master), 两 个从节点(redis-slave1, redis-slave2). 当主节点出现故障, 就会触发重新⼀系列过程.
1. 主观下线
当 redis-master 宕机, 此时 redis-master 和三个哨兵之间的⼼跳包就没有了. 此时, 站在三个哨兵的⻆度来看, redis-master 出现严重故障. 因此三个哨兵均会把 redis-master 判定为主观下线(SDown)
2. 客观下线
此时,哨兵 sentenal1, sentenal2, sentenal3 均会对主节点故障这件事情进⾏投票.,当故障得票数 >= 配置的法定票数之后,此时意味着 redis-master 故障这个事情被做实了,此时触发客观下线 (ODown)
3. 选举出哨兵的 leader
接下来需要哨兵把剩余的 slave 中挑选出⼀个新的 master. 这个⼯作不需要所有的哨兵都参与. 只需要 选出个代表 (称为 leader), 由 leader 负责进⾏ slave 升级到 master 的提拔过程,这个选举的过程涉及到 Raft 算法
简⽽⾔之,Raft 算法的核⼼就是 "先下⼿为强",谁率先发出了拉票请求,谁就有更⼤的概率成为 leader.
4. leader 挑选出合适的 slave 成为新的 master
挑选规则:
- ⽐较优先级:优先级⾼(数值⼩的)的上位,优先级是配置⽂件中的配置项( slave-priority 或者 replica-priority );
- ⽐较 replication offset 谁复制的数据多,⾼的上位;
- ⽐较 run id ,谁的 id ⼩,谁上位.
当某个 slave 节点被指定为 master 之后:
- leader 指定该节点执⾏ slave no one,成为 master ;
- leader 指定剩余的 slave 节点,都依附于这个新 master.