一边搭建一边理解MongoDB副本集(副本集选举)
副本集使用选举来决定那个成员成为主节点。在初始化副本集之后或者主节点不可用时,将会举行选举。主节点是副本集中唯一能够接受写请求的成员。如果主节点不可用了,选举能够让副本集恢复正常操作而不需要手工干预。在下面三个成员的副本集中,主节点不可用了,剩余的从节点之一发起了选举并选举自己成为新的主节点。
选举对于副本集的独立操作至关重要;但是选举需要时间来完成。当选举正在进行时,副本集没有主节点并且不能接受写请求同时所有的成员都是只读的。
如果副本集的大部分成员不可达或者不能被当前主节点访问,主节点会退位成为从节点。发生这种情况后,副本集不接受写请求,但是如果配置了从节点可读,副本集的剩余成员可以继续处理读查询。
影响选举的条件和因素
副本集选举协议
版本3.2新增:MongoDB引入了版本1的复制协议(protocolVersion:1)来降低副本集故障转移时间,并加速检查多个主节点的存在。新的副本集默认使用protocolVersionL1。之前版本的MongoDB使用该协议的版本0。
心跳
副本集成员每两秒互相发送心跳(pings)包。如果心跳包没有在10秒内返回,其他成员会标记这个失职的成员为不可达状态。
成员优先级
在副本集拥有稳定的主节点之后,选举算法会尽力使具有最高优先级的从节点发起选举。成员优先级同时影响了选举的时间和结果;具有高优先级的从节点发起选举比低优先级发起速度更快,同时也更容易赢得选举。但是在高优先级从节点可用时,低优先级成员可以短期内成为主节点。副本集成员继续发起选举知道最高优先级的可用成员成为主节点。
0优先级的成员不会成为主节点并且不会寻找选举。详见优先级0副本集成员。
数据中心故障
对于分布式副本集,数据中心故障可能影响位于其他数据中心剩余成员的能力或数据中心选择主节点。
如果可能,在数据中心之间分配副本集成员来最大化即使一个数据中心故障,剩余副本集成员之一可以成为主节点的可能性。
网络分区
网络分区可能把主节点隔离为具有少数成员的分区。当主节点检测到自己只能看到副本集中少数时,他会从主节点退位为从节点。同时,在分区中可以与大多数成员(包括自己)通信的成员会发起选举并成为新的主节点。
选举投票
版本3.2变更:protocolVersion:1消除了否决的需要。下面的否决讨论应用于使用protocolVersion:0的副本集。
对于使用protocolVersion:0的副本集,所有副本集成员可以否决选举,包括不能投票的成员,一个成员会否决选举在:
- 如果寻找选举的成员不在投票者集合中。
- 在其他投票者角度,如果当前主节点比寻找选举的成员拥有最近的操作(比如更高的optime)。
- 如果当前主节点比寻找选举的成员拥有最近或相同的操作(比如更高或相等的optime)。
- 如果0优先级成员在选举时是最新的成员。在这个情况下,副本集中另外合适的成员将赶上0优先级成员的状态,然后尝试成为主节点。
- 如果寻找选举的成员与另一个可以参与选举的成员相比优先级更低。
选举成员
副本集成员的设置members[n].votes和status决定了成员是否在副本集中投票。
- 所有在副本集中设置members[n].votes为1的成员可以在选举中投票。要在选举投票成员中排除掉一个成员,可以改变成员的members[n].votes为0。
- 只有以下状态的成员可以投票:
- PRIMARY
- SECONDARY
- RECOVERING
- ARBITER
- ROLLBACK
不投票成员
尽管不投票成员不能在选举中投票,这些成员拥有副本集数据的拷贝并且可以从应用程序客户端接受写请求。
例如,下面9个成员的副本集拥有7个投票成员和2个不投票成员。
一个不投票成员在他的配置中members[n].votes等于0。
{
"_id" : <num>
"host" : <hostname:port>,
"votes" : 0
}
不要改变votes的大小来控制哪个成员成为主节点。作为替代,使用members[n].priority选项。只有在特殊的情况在调整votes的大小,比如,为了允许大于7个成员投票。