本章内容:
- 影响选举的因素和条件(Factors and Conditions that Affect Elections)
- 投票成员(Voting Members)
- 非投票成员(Non-Voting Members)
副本集通过选举来确定哪个集合成员将成为主成员(primary)。多种事件都会导致副本集发起一轮选举,例如:
- 向副本集添加新节点,
- 启动副本集,
- 使用诸如rs.stepDown()或rs.reconfig()等方法进行副本集维护,
- 辅助成员(secondary members)与primary成员失连超过配置超时时间(默认10秒)。
在下图中,主(primary)节点不可用的时间超过配置的超时时间,并触发自动故障转移( automatic failover)过程。其余的辅助节点(secondaries)之一要求选择新的主节点并自动恢复正常操作。
新primary成员选举示意图。
在具有两个辅助节点的三成员副本集中,primary节点变得不可访问。失去primary候选人会触发选举,secondary候选人中会有一个会成为新的primary候选人。
在选举成功前,副本集无法处理写入操作。如果查询操作配置在辅助副本上运行,则副本集可以继续为读取查询提供服务。
默认的副本设置,群集选择新的主节点的中值时间(中值时间:理解为平均时间)通常不应超过12秒。这时间包括将主节点标记为不可用、发起并完成一轮选举所需的时间。可以通过修改settings.electionTimeoutMillis副本配置选项来调整此时间段。网络延迟之类的因素可能会延长完成副本集选举所需的时间,进而影响群集在没有主数据库的情况下可以运行的时间。这些因素取决于特定群集体系结构的不同。
我们的应用程序连接逻辑应包含对自动故障转移和后续选举的容忍度。从MongoDB 3.6开始,MongoDB驱动程序可以检测到主数据丢失,并可以进行一次自动重试某些写操作,提供了自动故障转移和选举的内置处理:
- 与MongoDB 4.2兼容的驱动程序默认情况下启用可重试写入
- 与MongoDB 4.0和3.6兼容的驱动程序必须通过在连接字符串中包含retryWrites = true来显式启用可重试写入。
一、影响选举的因素和条件
1.副本的选举协议
在版本4.0中进行了更改:MongoDB 4.0删除了不推荐使用的副本协议版本0。
副本protocolVersion:1减少了副本集故障转移时间,并加快了对多个同时存在的主节点的检测。
使用protocolVersion 1,可以使用catchUpTimeoutMillis在更快的故障转移和保留w:1写入之间确定优先级。
有关pv1的详细信息,请参阅副本集协议版本。
2.心跳
副本集成员每两秒钟彼此发送一次心跳(ping)。如果心跳在10秒钟内未返回,则其他成员将不良成员标记为不可访问。
3.成员的优先级
当副本集有了稳定的主节点后,选举算法将进行“尽力”使具有最高优先级的辅助节点可以发起一轮选举。
成员的优先权会影响选举的时间和结果;具有较高优先级的辅助节点的完成选举时间比较低优先级的辅助节点相对更快,而且也更有可能获胜。
但是,即使高优先级的辅助节点可用,低优先级的实例在某时间段内仍然可能被选为主节点。副本集成员会继续进行选举,直到具有最高优先级的成员成为主节点为止。
优先级为0的成员不能成为主节点,也不能谋求选举。有关详细信息,请参阅优先级为0的副本集成员。
4.数据中心丢失
使用分布式副本集时,数据中心的丢失可能会影响其他一个或多个数据中心剩余成员选举主节点的能力。
如果可能,请在数据中心之间分布副本集成员,以最大程度地确保即使丢失数据中心,其余副本集成员之一也可以成为新的主成员的可能性。
参考资料:
5.网络分区
网络分区可能将主节点隔离到具有少数节点的分区中。当主节点检测到只能看到副本集中的少数节点时,该主节点将降级主节点并成为辅助节点。同时,可以与大多数节点(包括自身)进行通信的分区中的成员进行选举以成为新的主节点。
二、投票成员
副本集成员通过配置member [n] .votes和成员state 确定成员在选举中是否有投票权。
1.member [n] .votes配置值等于1的副本集成员可以在选举中投票。要在选举中排除成员投票,将成员的member [n] .votes值更改为0。
在版本3.2中进行了更改:
- 非投票成员的优先级( priority)必须为0。
- 优先级大于0的成员member [n] .votes不能是0。
2.只有以下状态的投票成员才有资格投票:
三、非投票成员
尽管无投票权的成员不会在选举中投票,但这些成员会保留副本集数据的副本,并且可以接受来自客户端应用程序的读取操作。
由于副本集最多可以有50个成员,而只有7个投票成员,因此非投票成员在副本集中可以具有七个以上。
非投票成员的优先级( priority)必须为0。
例如,下面是一个9成员副本集:具有7个投票成员和2个非投票成员。
具有最多7个投票成员的9成员副本集示意图。
非投票成员的票数和优先级(votes and priority)均等于0:
{
"_id" : <num>,
"host" : <hostname:port>,
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 0
}
重要提示
请勿更改投票数(votes)以控制哪些成员将成为主成员。而是,修改members [n] .priority选项。仅在特殊情况下更改投票数。例如,允许超过七个成员。
要配置非投票成员,请参阅配置非投票副本集成员。