MongoDB副本集搭建

MongoDB的复制主要分2种,一种是Master-Salve(主从复制),一种是副本集(replica sets),MongoDB4.0之后就不支持主从复制了,官方原话

MongoDB 4.0 removes support for the deprecated master-slave replication. Before you can upgrade to MongoDB 4.0, if your deployment uses master-slave replication, you must upgrade to a replica set.

MongoDB 4.0删除了对主从复制的支持。在升级到MongoDB 4.0之前,如果部署使用主从复制,则必须升级到副本集.本文只讲解副本集的部署步骤。副本集相比较主从复制而言有2点区别:

  1. 该集群没有特定的主数据库。

  2. 如果哪个主数据库宕机了,集群中就会推选出一个从属数据库作为主数据库顶上,这就具备了自动故障恢复功能,很牛X的啊。

角色说明:

1.主库

理论上所有副本集中的数据库都能读取数据,但是系统会默认让主库来完成读取数据的功能

2.辅助副本

主服务器是副本集中唯一接收写操作的成员。MongoDB在主服务器上应用写操作,然后在主服务器的oplog上记录操作。辅助成员复制此日志并将操作应用于其数据集。

3.仲裁者

在主库宕机后重新投票选举出新的主库,它自己不能是主库也不能是辅助副本

副本集配置

1.创建每个库的配置文件,日志文件和数据存档的目录,我本机选择的是 /Data/MongoReplSet/下,MongoReplSet也是我自建的

MongoReplSet下的目录结构


├── conf

│   ├── db1.conf

│   ├── db2.conf

│   └── db3.conf

├── dbs

│   ├── db1

│   ├── db2

│   └── db3

└── logs

    ├── db1.log

    ├── db2.log

    └── db3.log

conf下的配置内容,其中replSet的值是这个副本集的名称

db1.conf
dbpath=/Data/MongoReplSet/dbs/db1
logpath=/Data/MongoReplSet/logs/db1.log
logappend=true
noprealloc=true
port=27011
fork=true
replSet=test

db2.conf
dbpath=/Data/MongoReplSet/dbs/db2
logpath=/Data/MongoReplSet/logs/db2.log
logappend=true
noprealloc=true
port=27012
fork=true
replSet=test

db3.conf
dbpath=/Data/MongoReplSet/dbs/db3
logpath=/Data/MongoReplSet/logs/db3.log
logappend=true
noprealloc=true
port=27013
fork=true
replSet=test

2.进入3个实例中的任何一个,初始化副本集


mongo --port 27011



use admin

config={

    _id:'test',

    members:[

        {_id:1, host:'localhost:27011',priority:2},

        {_id:2, host:'localhost:27012',priority:1},

        {_id:3, host:'localhost:27013',arbiterOnly:true}

    ]

}



rs.initiate(config)

_id:'test'表示副本集名称,与前面conf配置文件中的replSet参数配置的名称要一致。

priority:2表示优先级,优先级越高,副本集初始化时会选举为主库。arbiterOnly:true表示该实例为仲裁节点,不存储数据,只参与投票。

3.rs.status()查看副本集状态


test:SECONDARY> rs.status()

{

"set" : "test",

"date" : ISODate("2019-03-05T05:44:28.581Z"),

"myState" : 2,

"term" : NumberLong(0),

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"heartbeatIntervalMillis" : NumberLong(2000),

"optimes" : {

"lastCommittedOpTime" : {

"ts" : Timestamp(0, 0),

"t" : NumberLong(-1)

},

"appliedOpTime" : {

"ts" : Timestamp(1551764659, 1),

"t" : NumberLong(-1)

},

"durableOpTime" : {

"ts" : Timestamp(1551764659, 1),

"t" : NumberLong(-1)

}

},

"lastStableCheckpointTimestamp" : Timestamp(0, 0),

"members" : [

{

"_id" : 1,

"name" : "localhost:27011",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 108,

"optime" : {

"ts" : Timestamp(1551764659, 1),

"t" : NumberLong(-1)

},

"optimeDate" : ISODate("2019-03-05T05:44:19Z"),

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "could not find member to sync from",

"configVersion" : 1,

"self" : true,

"lastHeartbeatMessage" : ""

},

{

"_id" : 2,

"name" : "localhost:27012",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 8,

"optime" : {

"ts" : Timestamp(1551764659, 1),

"t" : NumberLong(-1)

},

"optimeDurable" : {

"ts" : Timestamp(1551764659, 1),

"t" : NumberLong(-1)

},

"optimeDate" : ISODate("2019-03-05T05:44:19Z"),

"optimeDurableDate" : ISODate("2019-03-05T05:44:19Z"),

"lastHeartbeat" : ISODate("2019-03-05T05:44:28.245Z"),

"lastHeartbeatRecv" : ISODate("2019-03-05T05:44:28.124Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "",

"configVersion" : 1

},

{

"_id" : 3,

"name" : "localhost:27013",

"health" : 1,

"state" : 7,

"stateStr" : "ARBITER",

"uptime" : 8,

"lastHeartbeat" : ISODate("2019-03-05T05:44:28.245Z"),

"lastHeartbeatRecv" : ISODate("2019-03-05T05:44:27.654Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "",

"configVersion" : 1

}

],

"ok" : 1,

"operationTime" : Timestamp(1551764659, 1),

"$clusterTime" : {

"clusterTime" : Timestamp(1551764659, 1),

"signature" : {

"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

"keyId" : NumberLong(0)

}

}

}

members下面就是整个副片集的成员,其中 27011端口号下面的 infoMessage:‘could not find member to sync from’,表示它没有可以同步的数据集,因为他是主库,只负责写入

4.主库添加测试数据


test:PRIMARY> use test

switched to db test

test:PRIMARY> db.person.insertMany([{"name":"tom", "age": 20}, {"name":"jack", "age":21}, {"name":"luna", "age":18}])

{

"acknowledged" : true,

"insertedIds" : [

ObjectId("5c7e13b79d270105c2390fcd"),

ObjectId("5c7e13b79d270105c2390fce"),

ObjectId("5c7e13b79d270105c2390fcf")

]

}

进副库检查


mongo --port 27012

test:SECONDARY> show dbs

2019-03-05T14:14:44.483+0800 E QUERY    [js] Error: listDatabases failed:{

"operationTime" : Timestamp(1551766483, 1),

"ok" : 0,

"errmsg" : "not master and slaveOk=false",

"code" : 13435,

"codeName" : "NotMasterNoSlaveOk",

"$clusterTime" : {

"clusterTime" : Timestamp(1551766483, 1),

"signature" : {

"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

"keyId" : NumberLong(0)

}

}

} :

发现没有权限查看,临时解决方案 执行 rs.slaveOk()


test:SECONDARY>  rs.slaveOk()

test:SECONDARY> show collections

person

test:SECONDARY> db.person.find()

{ "_id" : ObjectId("5c7e652ecf158632e56497cb"), "name" : "jack", "age" : 21 }

{ "_id" : ObjectId("5c7e652ecf158632e56497cc"), "name" : "luna", "age" : 18 }

{ "_id" : ObjectId("5c7e652ecf158632e56497ca"), "name" : "tom", "age" : 20 }

点赞