MongoDB复制集原理

Mongodb复制集由一组mongod实例组成,包含一个Primary节点和多个Secondary节点,数据写入Primary后,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用。

数据复制

当一个修改操作,无论是插入、更新或删除,到达Primary节点时,它对数据的操作将被记录下来,这些记录就是oplog。官方文档中的描述是:

The oplog (operations log) is a special capped collection that keeps a rolling record of all operations that modify the data stored in your databases.

Primary上的写操作完成后,会向特殊的local.oplog.rs特殊集合写入一条oplog,Secondary节点通过在Primary节点上打开一个tailable游标不断获取新进入Primary节点的oplog,并在自己的数据上回放,以此保持跟Primary节点的数据一致。

Tailable cursors are conceptually equivalent to the tail Unix command with the -f option (i.e. with “follow” mode)

Primary选举

MongoDB的复制集中最多可以有50个节点,具有投票权的节点最多7个。MongoDB 3.2版本之前选举协议是基于Bully算法,从3.2版本开始基于RAFT一致性算法实现,选举成功的必要条件是大多数投票节点存活。

具有投票权的节点之间两两互相发送心跳包,当5次心跳未收到时判断为节点失联,如果失联的是Primary节点,Secondary节点会发起选举,选出新的Primary节点,如果失联的是Secondary节点则不会产生新的选举。

被选举为Primary节点的节点必须具备以下条件:

  • 能够与多数节点建立连接
  • 具有较新的oplog
  • 具有较高的优先级(如果有配置)

复制集选项

  • 是否具有投票权: 有则参与投票
  • Priority(优先级): 优先级越高的节点越能优先成为Primary节点,优先级为0的节点不能触发选举,无法成为Primary节点,其他与普通的Secondary节点一样,维护数据集的副本,接受读取操作,并能够在选举中投票;
  • hidden(隐藏节点): 隐藏节点能够复制数据,但对应用来说不可见,具备投票权,但优先级必须为0,即无法称为Primary节点,可使用Hidden节点做一些数据备份、离线计算的任务,不会影响复制集的服务。
  • slaveDelay(延迟): 复制n秒之前的数据,保持与Primary节点的时间差。当错误或者无效的数据写入Primary节点时,可通过Delayed节点的数据来恢复到之前的时间点。

调整优先级

根据官方文档的步骤,尝试将其中一个节点的优先级降为0,首先进入Primary节点中,键入rs.conf()后,可以看到当前节点的信息,三个节点的优先级为"priority" : 1,:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
rs0:PRIMARY> cfg = rs.conf()
{
"_id" : "rs0",
"version" : 3,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "top:28018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {

},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
.......

接下来进行调整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rs0:PRIMARY> cfg.members[0].priority = 0
0
rs0:PRIMARY> rs.reconfig(cfg)
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1576506210, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1576506210, 1)
}
rs0:PRIMARY>

可以看到已经修改成功,此时members._id为0的节点已无法成为Primary节点了。

参考

1、MongoDB高手课
2、https://docs.mongodb.com/manual/core/replica-set-oplog/
3、https://docs.mongodb.com/manual/core/tailable-cursors/
4、http://www.mongoing.com/archives/2155
5、https://docs.mongodb.com/manual/administration/replica-set-member-configuration/

0%