复制集(Replica Set)是MongoDB核心组件,相比早期版本采用的主从(Master-Slave)架构,复制集具有很多天然的优势,包括自动故障恢复、多机房部署、读写行为控制等。本文介绍复制集中最基础的部分,就是复制集成员(Replica Set Member)。大体分为成员的角色及转换、成员状态及转换两部分。

先来说说成员角色,可分为Primary、Secondary和Arbiter三类。其中前两种是常规角色,每个复制集在正常状态下都会有这两种角色,Arbiter是一种特殊角色,其不包含用户数据,仅在选举时起作用。在这之中,Secondary又可以细分出很多熟悉,详见下面描述。

MongoDB在分布式架构上与Raft相类似,其Leader被称为Primary,Follower称为Secondary,但MongoDB中没有定义candidate角色。Primary即复制集的主节点,是唯一有权限接受客户端写请求的节点,会将所有的插入和更新操作记录到oplog中,Primary也是默认所有读请求的目标节点。Secondary复制Primary(或其他Secondary)的oplog记录并本地回放,来保持与Primary数据一致,可设置为允许客户端读,但默认情况下Secondary不允许读,需要设置slaveok参数。
MongoDB复制集成员及状态转换

Arbiter与上述两种角色不同,其不包含用户数据副本,复制集中添加Arbiter的目的仅仅是为了选主操作。通常在拥有偶数个节点的复制集中添加(且仅能添加)一个Arbiter,这样可以使一次选举中达到大多数(majority)而避免选举分裂(split vote)。如下所示:
MongoDB复制集成员及状态转换

当Primary因为某些原因挂掉或降级时,Secondary可通过选举成为新的Primary,原Primary恢复并重新加入复制集后,变为Secondary。Arbiter由于不包含用户数据,所以不可能成为Primary。这是他们间的相互转换关系。Primary、Secondary和Arbiter应独立部署在不同的网络节点上,对于云环境下,也不能位于相同的宿主机上,确保相互间数据安全性和选举独立性。

一个复制集中仅有一个Primary,在某些特殊场景下,可能没有Primary。Arbiter在集群中不是必须的。所以,集群中最普通的角色是Secondary,一般不少于2个。不同的Secondary可以有不同的属性,处于不同的状态中。Secondary属性有如下几类:

与选举相关的属性:

1、 是否能被选为Primary,该属性由priority控制,priority越高,就越有机会成为Primary,通常情况下,Primary总是复制集中priority最高的成员,priority为0的Secondary不能被选为Primary,该特性一般用于跨机房部署时,避免failover后新Primary切到另一个机房;
MongoDB复制集成员及状态转换

2、 是否有选举权,MongoDB复制集可以有多大50个成员,但仅允许7个成员有选举权,该属性由votes控制,votes为0的成员没有选举权,但可以否决选举,也可以成为Primary(可以理解为无法投赞成票,都可以投反对票和发起选举,因为被选举权由priority控制)。MongoDB 3.0版本开始,不允许设置成员的votes大于1。
MongoDB复制集成员及状态转换

与客户端相关的属性:

1、客户端是否可见,该参数由hidden控制,hidden为true表示不可见,客户端无法从该节点读取数据,mongos不会跟其交互;由于对客户端不可见,则肯定不能被选举为Primary,所以其priority属性必须为0;该节点一般用于进行备份等用途。
MongoDB复制集成员及状态转换

与数据延迟相关的属性:

1、slaveDelay用于控制该Secondary节点跟Primary节点的复制延迟关系,例如slaveDelay为3600,表示其数据相比Primary落后1小时,延迟判断是通过oplog中的信息来确定。该属性一般作为在线的历史备份,用来回滚人为操作导致的错误,包括误删除数据库或集合等;该属性潜在地需要priority属性为0,hidden属性为true;
MongoDB复制集成员及状态转换

可以看出,相比MySQL的Replication,MongoDB的Replica Set成员的类型和属性更为丰富,当然,主要原因是MySQL目前还是Master-Slave主从复制,所以与选举相关的属性或角色就没有存在的必要。但,MySQL也有类似的slaveDelay功能。另外,尚处于实验室状态MySQL Group Replication正式发布将会惊动数据库界。

聊完类型和属性,下面再来看看成员状态,不多不少,MongoDB一共有10种状态,官方将其分为3大类,核心状态(Core States)为三种成员类型对应的属性(PRIMARY/SECONDARY/ARBITER),还有7种属性,被分为其他状态(Other States)和错误状态(Error States)两类。
MongoDB复制集成员及状态转换

按照时间序,其他状态分别为STARTUP、STARTUP2和RECOVERING。每个复制集成员在mongod启动后,都先进入STARTUP状态,然后加载成员的复制集配置,之后进入到STARTUP2状态。如果该成员需要进行初始同步(initial sync),那么它将长期处于该状态,知道同步完所有的数据和索引。随后进入到RECOVERING状态,处于该状态的成员不能接受客户端的读请求,也不能被选举为Primary,但可以进行投票选举。

错误状态如下所示:若成员已加入了复制集,但还未进行状态信息同步的,会被其他复制集成员标记为UNKNOWN;若成员不再能够通过心跳来进行状态同步,即失去联系,则被其他成员标记为DOWN;REMOVED表示该成员已经被移出复制集;成员处于rollback过程时,状态为ROLLBACK,该状态在旧的primary重新加入复制集时可能出现,用于回滚其上还未同步到其他Secondary的操作;FATAL状态表示成员遇到了无法恢复的错误,必须进行人工处理。

选举行为除了受vote和priority两个属性影响外,成员的状态也会影响选举,仅有PRIMARY, SECONDARY, RECOVERING, ARBITER和ROLLBACK五种状态的成员允许进行投票操作。