在了解到了MongoDB复制集的体系架构以后,下面将通过具体的步骤来演示如何搭建单个节点的MongoDB复制集环境。下表列举了MongoDB复制集的配置信息。
提示:上表在一台主机上通过监听不同的端口来搭建MongoDB复制集环境,也可以使用三台主机来搭建。
视频讲解如下:
下面是具体的搭建步骤:
(1)创建MongoDB复制集每个节点数据存储的目录。
mkdir -p /data/primary/ mkdir -p /data/slave01/ mkdir -p /data/slave02/
(2)编辑主库的配置文件/data/primary/mongo_primary.conf。
dbpath=/data/primary/ port=27017 fork=true logpath=/data/primary/primary.log replSet=mycluster
提示:在搭建MongoDB复制集环境时,最重要的参数就是replSet。该参数将用于标识该节点从属的复制集信息。
(3)编辑第一个从库的配置文件/data/slave01/mongo_slave01.conf。
dbpath=/data/slave01/ port=27018 fork=true logpath=/data/slave01/slave01.log replSet=mycluster
(4)编辑第二个从库的配置文件/data/slave02/mongo_slave02.conf
dbpath=/data/slave02/ port=27019 fork=true logpath=/data/slave02/slave02.log replSet=mycluster
(5)使用mongod命令启动每个节点。
mongod --config /data/primary/mongo_primary.conf mongod --config /data/slave01/mongo_slave01.conf mongod --config /data/slave02/mongo_slave02.conf
(6)确定MongoDB实例监听的地址信息。
netstat -ntulp | grep mongod # 输出的信息如下: tcp 0 0 127.0.0.1:27019 0.0.0.0:* LISTEN 46922/mongod tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 46804/mongod tcp 0 0 127.0.0.1:27018 0.0.0.0:* LISTEN 46868/mongod
(7)使用mongoshell登录其中的一个MongoDB数据库实例。
mongo
(8)查看复制集的状态。
> rs.status() # 输出的信息如下: { "ok" : 0, "errmsg" : "no replset config has been received", "code" : 94, "codeName" : "NotYetInitialized" }
提示:MongoDB复制集在使用前需要先执行初始化。
(9)创建复制集的配置信息,将各个节点添加到复制集配置信息中。
> cfg = {"_id":"mycluster", "members":[{"_id":0,"host":"127.0.0.1:27017"}, {"_id":1,"host":"127.0.0.1:27018"}, {"_id":2,"host":"127.0.0.1:27019"}]}
(10)执行复制集的初始化
> rs.initiate(cfg)
(11)查看副本集的状态。
> rs.status() # 输出的信息如下: { "set" : "mycluster", "date" : ISODate("2022-04-06T04:03:05.729Z"), "myState" : 2, "term" : NumberLong(0), "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "votingMembersCount" : 3, "writableVotingMembersCount" : 3, ...... "members" : [ { "_id" : 0, "name" : "127.0.0.1:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 603, "optime" : { "ts" : Timestamp(1649217783, 1), "t" : NumberLong(-1) }, ...... }, { "_id" : 1, "name" : "127.0.0.1:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 2, "optime" : { "ts" : Timestamp(1649217783, 1), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(1649217783, 1), "t" : NumberLong(-1) }, ...... }, { "_id" : 2, "name" : "127.0.0.1:27019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 2, "optime" : { "ts" : Timestamp(1649217783, 1), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(1649217783, 1), "t" : NumberLong(-1) }, ...... } ], "ok" : 1, ...... }
提示:输出的三个节点信息包含以下的字段信息:
"stateStr" : "SECONDARY",
这说明MongoDB复制集正在执行选举的操作,此时的三个节点都是从库。
(12)等待一段时间,再次查看副本集的状态。
> rs.status() # 输出的信息如下: ...... "members" : [ { "_id" : 0, "name" : "127.0.0.1:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 961, ...... }, { "_id" : 1, "name" : "127.0.0.1:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 360, ...... }, { "_id" : 2, "name" : "127.0.0.1:27019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 360, ...... } ], ......
提示:MongoDB复制集经过选举后,27017的节点被选举成了主库,而27018和27019的节点成为了从库。
(13)在主库上创建一个集合并插入一条文档。
> use demo > db.test1.insert({name:'Tom'})
(14)在主库上查询文档。
> db.test1.find() # 输出的信息如下: { "_id" : ObjectId("624d13bc587b73632da622ce"), "name" : "Tom" }
(15)使用mongoshell登录到其中一个从库上,并查看数据库信息。
mongo --port 27018 > show dbs # 输出的错误信息如下: ...... uncaught exception: Error: listDatabases failed:{ "topologyVersion" : { "processId" : ObjectId("624d0ea30b93b269b4c404d6"), "counter" : NumberLong(4) }, "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk", "$clusterTime" : { "clusterTime" : Timestamp(1649218594, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1649218594, 1) } : ......
提示:在默认情况下,MongoDB复制集的从库是不可用的,需要手动启用从库。
(16)启用从库并查看数据库信息。
> rs.slaveOk() > show dbs # 输出的信息如下: admin 0.000GB config 0.000GB demo 0.000GB local 0.000GB
(17)查看demo数据库中的集合。
> use demo > db.test1.find()
(18)在从库上插入一条新的文档。
> db.test1.insert({name:'Mary'}) # 输出的错误信息如下: WriteCommandError({ "topologyVersion" : { "processId" : ObjectId("624d0ea30b93b269b4c404d6"), "counter" : NumberLong(4) }, "ok" : 0, "errmsg" : "not master", "code" : 10107, "codeName" : "NotWritablePrimary", "$clusterTime" : { "clusterTime" : Timestamp(1649221014, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1649221014, 1) })
提示:在MongoDB复制集的环境中从库是只读的状态。