复制的重要性不再多说,其主要就是提供数据保护,数据高可用和灾难恢复。
复制是跨多个mongodb服务器分布和维护的方法。mongodb可以把数据从一个节点复制到其他节点并在修改时进行同步。
mongodb的复制有两种方式: 副本集复制和主从架构复制。这两种方法类似,主节点接收所有的写请求,然后所有的从节点读取,并且异步同步所有的数据。
主从复制和副本集使用了相同的复制机制,但是副本集额外增加了自动化灾备机制,如果主节点宕机,无论什么原因,其中一个从节点会自动提升为主节点。除此之外副本集还提供了其他改进,比如更易于恢复和更复杂地部署网络拓扑。线上环境几乎全都是使用的副本集,因此这里只会有关于副本集的介绍。
下面会实际搭建一个最基本的副本集,然后会说明副本集的原理?
【MongoDB的启动必须从配置文件启动,不要用命令行】
第一步:配置文件中指定副本集的名称
#在三台服务器的配置文件中均要有如下设置 replication: oplogSizeMB: 20 #指定oplog的日志大小,注意这里大小只是为了测试 replSetName: lianxi #指定副本集的名称,在一个副本集中名称要保持一致
第二步:配置文件启动MongoDB服务器:
[root@test1 ~]# cd /usr/local/mongodb/bin [root@test1 bin]# ./mongod -f ../conf/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 2247 child process started successfully, parent exiting [root@test1 bin]#
第三步:配置副本集
#选中其中一台MongoDB服务器作为primary. [root@test2 bin]# ./mongo #进入shell交互界面 MongoDB shell version v3.4.2 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.2 Server has startup warnings: 2018-11-06T13:13:43.676+0800 I STORAGE [initandlisten] 2018-11-06T13:13:43.676+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2018-11-06T13:13:43.676+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2018-11-06T13:13:43.809+0800 I CONTROL [initandlisten] 2018-11-06T13:13:43.809+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-11-06T13:13:43.809+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-11-06T13:13:43.809+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2018-11-06T13:13:43.809+0800 I CONTROL [initandlisten] > rs.initiate() #初始化操作 { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "test2:27017", "ok" : 1 } lianxi:SECONDARY> #初始化成功之后,提示会变为SECONDARY lianxi:PRIMARY> #敲下回车,会变为PRIMARY #初始化成功之后,添加副本集成员 lianxi:PRIMARY> rs.add("10.0.102.214:27017") #添加从节点 { "ok" : 1 } #添加仲裁节点 lianxi:PRIMARY> rs.addArb("10.0.102.220:27017") { "ok" : 1 }
若上面的步骤没有报错,说明副本集搭建成功。
说一个这里搭建遇见的一个问题:
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "test3:27017",
"ok" : 1
} #初始化成功
test_repl:SECONDARY> rs.add("10.0.102.181:27017") #添加节点成功【但是日志会在等一会之后报错】
{ "ok" : 1 }
test_repl:PRIMARY> rs.addArb("10.0.102.204:27017") #若不查看日志直接添加仲裁节点,会报如下错误!
2018-11-05T10:33:12.753+0800 E QUERY [thread1] Error: error doing query: failed: network error while attempting to run command 'count' on host '127.0.0.1:27017' :
DB.prototype.runCommand@src/mongo/shell/db.js:132:1
DB.prototype.runReadCommand@src/mongo/shell/db.js:109:16
DBQuery.prototype.count@src/mongo/shell/query.js:380:15
DBCollection.prototype.count@src/mongo/shell/collection.js:1700:12
rs.add@src/mongo/shell/utils.js:1213:1
rs.addArb@src/mongo/shell/utils.js:1253:12
@(shell):1:1
2018-11-05T10:33:12.756+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2018-11-05T10:33:12.757+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok
test_repl:SECONDARY> #这里的提示变为SECONDARY
这个问题查了好久,后来在日志文件中发现是第一步添加节点成功,日志就报错了意识是主节点连接不上从节点,但是在命令行指定host参数是可以连接的,于是就各种纠结!
最后无意中看了/etc/hosts文件,发现是hosts文件的域名解析指向错误。好吧,就是这里的问题!但是费了好长时间!
这个副本集中含有一个主节点用来写入数据,一个从节点,和一个仲裁节点,整个结构如下:
这是MongoDB副本集的最小的节点数量,一旦主宕机,根据选举原则(一个服务器一票)从服务器会被提升为主服务器继续提供服务。MongoDB副本集为了防止出现脑裂的情况,副本集的个数应该为奇数。
测试副本集:
查看当前副本集的状态,可以使用如下命令:
members数组中有三个成员,分别表示这主节点,从节点,和仲裁节点。
#在主上面写入数据 lianxi:PRIMARY> use mydb switched to db mydb lianxi:PRIMARY> db.cityinfo.insert({name: "HongKong", country: "CHINA"}) WriteResult({ "nInserted" : 1 }) lianxi:PRIMARY> #从上面查看数据 lianxi:SECONDARY> show dbs; #从上面需要执行slaveOK命令才能查看数据 2018-11-06T14:06:47.696+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435, "codeName" : "NotMasterNoSlaveOk" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1 shellHelper.show@src/mongo/shell/utils.js:755:19 shellHelper@src/mongo/shell/utils.js:645:15 @(shellhelp2):1:1 lianxi:SECONDARY> rs.slaveOk() #执行命令后 lianxi:SECONDARY> show dbs; admin 0.000GB local 0.000GB mydb 0.000GB lianxi:SECONDARY> use mydb switched to db mydb lianxi:SECONDARY> show collections; cityinfo lianxi:SECONDARY> db.cityinfo.find().pretty() #数据已经同步到从上 { "_id" : ObjectId("5be12eb19efff2d99afed619"), "name" : "HongKong", "country" : "CHINA" } lianxi:SECONDARY>