5.4 自动故障转移
在故障转移场景中,我们所关心的问题是:
● 备节点是怎么感知到主节点已经发生故障的?
● 如何降低故障转移对业务产生的影响?
下面来看一些细节。
图5-13是一个PSS(一主两备)架构的副本集,主节点除了与两个备节点执行数据复制,三个节点之间还会通过心跳感知彼此的存活。
图5-13 心跳机制
一旦主节点发生故障以后,备节点将在某个周期内检测到主节点处于不可达的状态,此后将由其中一个备节点事先发起选举并最终成为新的主节点,如图5-14所示。
图5-14 自动故障转移
一个影响检测机制的因素是心跳,在副本集组建完成之后,各成员节点会开启定时器,持续向其他成员发起心跳,这里涉及的参数为heartbeatIntervalMillis,即心跳间隔时间,默认值是2s。如果心跳成功,则会持续以2s的频率继续发送心跳;如果心跳失败,则会立即重试心跳,一直到心跳恢复成功。
另一个重要的因素是选举超时检测,一次心跳检测失败并不会立即触发重新选举。实际上除了心跳,成员节点还会启动一个选举超时检测定时器,该定时器默认以10s的间隔执行,具体可以通过electionTimeoutMillis参数指定:
● 如果心跳响应成功,则取消上一次的electionTimeout调度(保证不会发起选举),并发起新一轮electionTimeout调度。
● 如果心跳响应迟迟不能成功,那么electionTimeout任务被触发,进而导致备节点发起选举并成为新的主节点。
因此,在electionTimeout任务中触发选举必须要满足以下条件:
(1)当前节点是备节点。
(2)当前节点具备选举权限。
(3)在检测周期内仍然没有与主节点心跳成功。
整个选举切换的逻辑如图5-15所示。
图5-15 自动选举的实现逻辑
在MongoDB的实现中,选举超时检测的周期要略大于electionTimeoutMillis设定。该周期会加入一个随机偏移量,大约在10~11.5s,如此的设计是为了错开多个备节点主动选举的时间,提升成功率。
业务影响评估
● 在副本集发生主备节点切换的情况下,会出现短暂的无主节点阶段,此时无法接受业务写操作。如果是因为主节点故障导致的切换,则对于该节点的所有读写操作都会产生超时。如果使用MongoDB 3.6及以上版本的驱动,则可以通过开启retryWrite来降低影响。
● 如果主节点属于强制掉电,那么整个Failover过程将会变长,很可能需要在Election定时器超时后才被其他节点感知并恢复,这个时间窗口一般会在12s以内。然而实际上,对于业务呼损的考量还应该加上客户端或mongos对于副本集角色的监视和感知行为(真实的情况可能需要长达30s以上)。
● 对于非常重要的业务,建议在业务层面做一些防护策略,比如设计重试机制。