在每个MongoDB(版本 3.4.2) Instance中,都有一个本地数据库(local),用于存储 Replication 进程的信息和本地数据。local 数据库的特性是:位于local数据库中的数据和集合不会被 Replication 进程复制到其他MongoDB instance上。如果实例上有些collection 和 data不计划被复制到其他MongoDB Instance,可以将这些collection 和 data 存储在local 数据库中。
成员的配置文档:
priority:表示一个成员被选举为Primary节点的优先级,默认值是1,取值范围是从0到100,将priority设置为0有特殊含义:Priority为0的成员永远不能成为Primary 节点。Replica Set中,Priority最高的成员,会优先被选举为Primary 节点,只要其满足条件。
hidden:将成员配置为隐藏成员,要求Priority 为0。Client不会向隐藏成员发送请求,因此隐藏成员不会收到Client的Request。
slaveDelay:单位是秒,将Secondary 成员配置为延迟备份节点,要求Priority 为0,表示该成员比Primary 成员滞后指定的时间,才能将Primary上进行的写操作同步到本地。为了数据读取的一致性,应将延迟备份节点的hidden设置为true,避免用户读取到明显滞后的数据。Delayed members maintain a copy of the data that reflects the state of the data at some time in the past.
votes:有效值是0或1,默认值是1,如果votes是1,表示该成员(voting member)有权限选举Primary 成员。在一个Replica Set中,最多有7个成员,其votes 属性的值是1。
arbiterOnly:表示该成员是仲裁者,arbiter的唯一作用是就是参与选举,其votes属性是1,arbiter不保存数据,也不会为client提供服务。
buildIndexes:表示实在在成员上创建Index,该属性不能修改,只能在增加成员时设置该属性。如果一个成员仅仅作为备份,不接收Client的请求,将该成员设置为不创建index,能够提高数据同步的效率。
1.创建三个节点目录如下图:
节点一:
节点二:
节点三:
2.对上面的三个节点分别在cfg文件下新增配置文件
节点一配置文件:
logpath=D:\data1\logs\mongod.log
dbpath=D:\data1\db
logappend=true
#auth=true
port=27018
replSet=rs0
节点二配置文件:
logpath=D:\data2\logs\mongod.log
dbpath=D:\data2\db
logappend=true
#auth=true
port=27019
replSet=rs0
节点三配置文件:
logpath=D:\data3\logs\mongod.log
dbpath=D:\data3\db
logappend=true
#auth=true
port=27020
replSet=rs0
3.在每个节点下面配置配置启动mongo数据库实例start1.bat、start2.bat、start3.bat
节点一:mongod --config D:\data1\cfg\mongod.cfg----start1.bat
节点二:mongod --config D:\data2\cfg\mongod.cfg----start2.bat
节点三:mongod --config D:\data3\cfg\mongod.cfg----start3.bat
4.启动上面的三个bat文件
5.连接上节点一并执行如下命令:
var config_rs = {_id : "rs0",members : [ { _id:0, host:"127.0.0.1:27018", priority:1 },{ _id:1, host:"127.0.0.1:27019", priority:1 },{ _id:2, host:"127.0.0.1:27020", priority:1, "arbiterOnly": true } ]}
rs.initiate(config_rs)
输入rs.status结果如下:
/* 1 */
{
"set" : "rs0",
"date" : ISODate("2017-06-26T08:48:15.107Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27018",
"health" : 1.0,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 125,
"optime" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-06-26T08:48:09.000Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1498466808, 1),
"electionDate" : ISODate("2017-06-26T08:46:48.000Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "127.0.0.1:27019",
"health" : 1.0,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 98,
"optime" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1498466889, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-06-26T08:48:09.000Z"),
"optimeDurableDate" : ISODate("2017-06-26T08:48:09.000Z"),
"lastHeartbeat" : ISODate("2017-06-26T08:48:14.262Z"),
"lastHeartbeatRecv" : ISODate("2017-06-26T08:48:14.660Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "127.0.0.1:27018",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "127.0.0.1:27020",
"health" : 1.0,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 98,
"lastHeartbeat" : ISODate("2017-06-26T08:48:14.263Z"),
"lastHeartbeatRecv" : ISODate("2017-06-26T08:48:13.559Z"),
"pingMs" : NumberLong(0),
"configVersion" : 1
}
],
"ok" : 1.0
}
通过结果可以看到主节点和副节点及裁判节点,主节点接受所有的读写操作,在主节点的所有更改都会同步奥副节点上去。
MongoDB shell提供一个全局变量rs,是数据库命令的包装器(wrapper),用于维护Replica Set。
MongoDB 将Replica Set的配置信息存储在local.system.replset 集合中,在同一个Replica Set中所有成员local.system.replset是相同的,不能直接修改该集合,必须通过rs.initiate()来初始化,通过 rs.reconfig()来重新配置,对Replica Set 增加或删除成员都会相应的修改Replica Set的配置信息。
重新配置Replica Set
对Replica Set重新配置,必须连接到Primary 节点;如果Replica Set中没有一个节点被选举为Primary,那么,可以使用force option(rs.reconfig(config,{force:true})),在Secondary 节点上强制对Replica Set进行重新配置。
The force parameter allows a reconfiguration command to be issued to a non-primary node. If set as { force: true }, this forces the replica set to accept the new configuration even if a majority of the members are not accessible. Use with caution, as this can lead to rollback situations.
示例,在primary 节点中,重新配置成员的优先级属性(priority)。
cfg = rs.conf()
cfg.members[0].priority = 1
cfg.members[1].priority = 1
cfg.members[2].priority = 5
rs.reconfig(cfg)
--增加一个成员,用于存储数据
rs.add("host:port")
--增加一个arbiter,用于选举
rs.add("host:port",true)
--删除一个成员
rs.remove("host")
Replica Set的操作日志
MongoDB的Replication实际上是基于操作日志(operation log)的复制。Replication进程的整个过程是:Replication 将Primary节点中执行的写操作记录到oplog集合中,Secondary成员读取Primary 成员的oplog集合,重做(redo)oplog中记录的写操作,最终,Replica Set中的各个成员达到数据的一致性。
oplog集合中记录的操作是基于单个doc的,也就是说,如果一条命令只影响一个doc,那么Replication向oplog集合中插入一个操作命令;如果一个命令影响多个doc,那么Replication将该命令拆分成多个等效的操作命令,每个操作命令只会影响一个doc,最终向oplog集合中插入的是多个操作命令。
1,oplog 集合
oplog集合是一个特殊的固定集合,存储的是Primary节点的操作日志,每个Replica Set的成员都一个oplog的副本:local.oplog.rs,该集合存储在每个成员的local数据库中。Replica Set中的每个成员都有一个oplog集合,用于存储当前节点的操作记录,其他成员能够从任何一个成员的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. MongoDB applies database operations on the primary and then records the operations on the primary’s oplog. The secondary members then copy and apply these operations in an asynchronous process. All replica set members contain a copy of the oplog, in the local.oplog.rs collection, which allows them to maintain the current state of the database.
2,oplog的大小
oplog集合是一个固定集合,其大小是固定的,在第一次开始Replica Set的成员时,MongoDB创建默认大小的oplog。在MongoDB 3.2.9 版本中,MongoDB 默认的存储引擎是WiredTiger,一般情况下,oplog的默认大小是数据文件所在disk 空闲空间(disk free space)的5%,最小不会低于990 MB,最大不会超过50 GB。