MongoDB的副本集可以实现自动主从切换的过程,这个过程是相对复杂的, 本文主要介绍其实现过程。
在MongoDB里面, 定义了如下的状态:
enum MS {
RS_STARTUP = 0,
RS_PRIMARY = 1,
RS_SECONDARY = 2,
RS_RECOVERING = 3,
RS_STARTUP2 = 5,
RS_UNKNOWN = 6, /* remote node not yet reached */
RS_ARBITER = 7,
RS_DOWN = 8, /* node not reachable for a report */
RS_ROLLBACK = 9,
RS_REMOVED = 10, /* node removed from replica set */
RS_MAX = 10
} s;
RS_STARTUP
每一个节点一开始的时候, 其状态会被设置成为RS_STARTUP。
RS_PRIMARY
RS_SECONDARY
RS_ARBITER
这3中状态是福呢么及节点的稳定状态,一个副本集只会含有一个primary节点, 若干个secondary, 以及一个arbiter节点。
RS_RECOVERING
表示节点要转变为secondary状态, 当前的状态还是在同步oplog或者回滚状态。
RS_STARTUP2
表示节点处于initial sync状态。
RS_UNKNOWN
该状态主要是用在heartbeat 的MemberHeartbeatData里面的ReplSetHeartbeatResponse, 记录某个节点的heartbeat相应数据, 如果该节点的没有正常相应或者有账号校验方面的问题, 就设定为RS_UNKNOWN, 以表示该节点状态未知。
RS_DOWN
该状态和RS_UNKNOWN类似, 都是根据heartbeat的结果来设定的, 与RS_UNKNOWN不通点在于, 它是确定所访问的节点发生故障或者不可达。
RS_ROLLBACK
该状态表是节点正在回滚中。
RS_REMOVED
表示该节点的配置文件已经被初始化过, 但是在heartbeat的结果里面找不到该节点, 已经被移出副本集;
这个过程有有最初的PreStart对应的RS_STARTUP, 到开始initialsync, 其对应的状态为RS_STARTUP2, 全量数据同步完成以后, 进入RS_RECOVERING状态, 最后进入RS_SECONDARY状态。
改过程可能是新的节点加入, 也可能是调用resync命令, 最终变成一个secondary节点。
这个过程, 从RS_PRIMARY, 到RS_ROLLBACK需要的话, 经过RS_RECOVERING, 最后变成RS_SECONDARY;
该过程其实是一个故障转移的过程, 节点由于主机或者网络故障, 从主节点变换为从节点的过程, 该过程中原本的secondary节点会重新选主,产生一个新的primary, 异常的旧的主节点重新加入副本集以后, 最终跟新的primary进行同步, 达到一致状态后, 变成secondary; 如果无法达成一致状态, 最终该节点在rollback阶段, 在向前找到第一个节点后还是没有找到一致的oplog, 程序会退出;
这个过程从RS_SECONDARY, 变成RS_PRIMARY;
这个过程其实是从节点选主的过程, 在旧的primary不可用的情况下, secondary会发起新的选主过程, 每一次选主, 都会产生一个新的term, 用来区分不同的节点同时选主, 以及受到该选主请求的时候, 进行区分。一旦某个节点得到大多数节点的赞同, 被选为主, 该节点会发起赢得选举的声明, 并将最新的主节点信息公布出去, 其他的正在等待选举结果的发起者, 取消选举;