mongodb的复制集,大致就是在主从复制的基础上,加入了高可用控制,类似高可用mysql集群
在主节点出现问题后,从节点会重新找出来一个主节点,系统自动完成,mysql如果也这样就完美了,mysql弄这个好复杂
1.
在linux 下面做3个账号连接,然后依次开启3个mongodb的进程(非守护进行,守护进程只能开启一个)
2.
/usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data1 -logpath=/mongodb/log1/log.log -port=10001 --replSet terry /usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data2 -logpath=/mongodb/log2/log.log -port=10002 --replSet terry /usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data3 -logpath=/mongodb/log3/log.log -port=10003 --replSet terry
查看是否运行成功:
[root@grande ~]# ps -ef | grep mongo root 2345 1 0 Nov27 ? 01:34:52 /usr/local/mongodb2.6/bin/mongod --dbpath=/usr/local/mongodb2.6/data -logpath=/usr/local/mongodb2.6/log -fork -port=27017 root 25111 24779 0 09:13 pts/1 00:00:12 /usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data2 -logpath=/mongodb/log2/log.log -port=10002 --replSet terry root 25157 24679 0 09:13 pts/0 00:00:12 /usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data1 -logpath=/mongodb/log1/log.log -port=10001 --replSet terry root 25203 24809 0 09:14 pts/2 00:00:11 /usr/local/mongodb2.6/bin/mongod --dbpath=/mongodb/data3 -logpath=/mongodb/log3/log.log -port=10003 --replSet terry root 25341 24854 0 09:17 pts/4 00:00:00 mongo 10.10.10.252:10001/admin root 25895 25288 0 09:38 pts/5 00:00:00 mongo 10.10.10.252:10002 root 26089 26069 0 09:44 pts/6 00:00:00 grep mongo
3. 通过上面的运行,我们还需要初始化:
mongo 10.10.10.252:10001/admin
db.runCommand({"replSetInitiate":{ "_id":"terry", "members":[ { "_id":1, "host":"10.10.10.252:10001" }, { "_id":2, "host":"10.10.10.252:10002" } ] } } )
{ "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 }
rs.status()
> rs.status() { "set" : "terry", "date" : ISODate("2015-12-08T01:17:08Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "10.10.10.252:10001", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 192, "optime" : Timestamp(1449537265, 1), "optimeDate" : ISODate("2015-12-08T01:14:25Z"), "electionTime" : Timestamp(1449537274, 1), "electionDate" : ISODate("2015-12-08T01:14:34Z"), "self" : true }, { "_id" : 2, "name" : "10.10.10.252:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 162, "optime" : Timestamp(1449537265, 1), "optimeDate" : ISODate("2015-12-08T01:14:25Z"), "lastHeartbeat" : ISODate("2015-12-08T01:17:06Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T01:17:06Z"), "pingMs" : 0, "syncingTo" : "10.10.10.252:10001" } ], "ok" : 1 }
rs.addArb("10.10.10.252:10003")
terry:PRIMARY> rs.addArb("10.10.10.252:10003") { "ok" : 1 } terry:PRIMARY> rs.status function () { return db._adminCommand("replSetGetStatus"); } terry:PRIMARY> rs.status() { "set" : "terry", "date" : ISODate("2015-12-08T01:18:29Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "10.10.10.252:10001", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 273, "optime" : Timestamp(1449537501, 1), "optimeDate" : ISODate("2015-12-08T01:18:21Z"), "electionTime" : Timestamp(1449537274, 1), "electionDate" : ISODate("2015-12-08T01:14:34Z"), "self" : true }, { "_id" : 2, "name" : "10.10.10.252:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 243, "optime" : Timestamp(1449537501, 1), "optimeDate" : ISODate("2015-12-08T01:18:21Z"), "lastHeartbeat" : ISODate("2015-12-08T01:18:28Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T01:18:28Z"), "pingMs" : 0, "syncingTo" : "10.10.10.252:10001" }, { "_id" : 3, "name" : "10.10.10.252:10003", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 8, "lastHeartbeat" : ISODate("2015-12-08T01:18:27Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T01:18:28Z"), "pingMs" : 0 } ], "ok" : 1 }
4. 执行查询会报错:
但此时在从库中查询报如下错误:
这是正常的现象,对于SECONDARY节点默认是不可读的。因为SECONDARY是不允许读和写的,在写多读少的应用中,使用Replica Sets来实现读写分离。通过在连接时指定或者在主库指定slaveOk,由SECONDARY来分担读的压力,PRIMARY只承担些操作。
解决方法:
第一种:在从节点设置slaveOk():
rs.slaveOk();
第二种:在主节点设置:
db.getMongo().setSlaveOk();
这样就可以查询了。
5. 增加新节点:
rs.add("10.10.10.252:10004");
terry:PRIMARY> rs.remove("10.10.10.252:10004"); 2015-12-08T10:30:15.336+0800 DBClientCursor::init call() failed 2015-12-08T10:30:15.339+0800 Error: error doing query: failed at src/mongo/shell/query.js:81 2015-12-08T10:30:15.341+0800 trying reconnect to 10.10.10.252:10001 (10.10.10.252) failed 2015-12-08T10:30:15.341+0800 reconnect 10.10.10.252:10001 (10.10.10.252) ok
terry:PRIMARY> rs.status(); { "set" : "terry", "date" : ISODate("2015-12-08T02:30:37Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "10.10.10.252:10001", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 4601, "optime" : Timestamp(1449541815, 1), "optimeDate" : ISODate("2015-12-08T02:30:15Z"), "electionTime" : Timestamp(1449537274, 1), "electionDate" : ISODate("2015-12-08T01:14:34Z"), "self" : true }, { "_id" : 2, "name" : "10.10.10.252:10002", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 22, "optime" : Timestamp(1449541815, 1), "optimeDate" : ISODate("2015-12-08T02:30:15Z"), "lastHeartbeat" : ISODate("2015-12-08T02:30:37Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T02:30:36Z"), "pingMs" : 0, "lastHeartbeatMessage" : "syncing to: 10.10.10.252:10001", "syncingTo" : "10.10.10.252:10001" }, { "_id" : 3, "name" : "10.10.10.252:10003", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 22, "lastHeartbeat" : ISODate("2015-12-08T02:30:37Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T02:30:36Z"), "pingMs" : 0 } ], "ok" : 1 }
7.测试切换
主节点停掉:
terry:PRIMARY> rs.status(); { "set" : "terry", "date" : ISODate("2015-12-08T03:03:14Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "10.10.10.252:10001", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : Timestamp(1449541815, 1), "optimeDate" : ISODate("2015-12-08T02:30:15Z"), "lastHeartbeat" : ISODate("2015-12-08T03:03:13Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T02:32:45Z"), "pingMs" : 0 }, { "_id" : 2, "name" : "10.10.10.252:10002", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 6565, "optime" : Timestamp(1449543736, 1), "optimeDate" : ISODate("2015-12-08T03:02:16Z"), "electionTime" : Timestamp(1449541974, 1), "electionDate" : ISODate("2015-12-08T02:32:54Z"), "self" : true }, { "_id" : 3, "name" : "10.10.10.252:10003", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 1979, "lastHeartbeat" : ISODate("2015-12-08T03:03:12Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T03:03:13Z"), "pingMs" : 0 }, { "_id" : 4, "name" : "10.10.10.252:10004", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 58, "optime" : Timestamp(1449543736, 1), "optimeDate" : ISODate("2015-12-08T03:02:16Z"), "lastHeartbeat" : ISODate("2015-12-08T03:03:12Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T03:03:12Z"), "pingMs" : 0, "lastHeartbeatMessage" : "syncing to: 10.10.10.252:10002", "syncingTo" : "10.10.10.252:10002" } ], "ok" : 1 }
id为2的变为PRIMARY
在yii2下链接是没有问题的
关于副本集的yii2的配置参看:
http://blog.csdn.net/terry_water/article/details/50215887
重新启动id为1的mongo:
terry:PRIMARY> rs.status(); { "set" : "terry", "date" : ISODate("2015-12-08T03:06:09Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "10.10.10.252:10001", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 4, "optime" : Timestamp(1449541815, 1), "optimeDate" : ISODate("2015-12-08T02:30:15Z"), "lastHeartbeat" : ISODate("2015-12-08T03:06:07Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T03:06:08Z"), "pingMs" : 52 }, { "_id" : 2, "name" : "10.10.10.252:10002", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 6740, "optime" : Timestamp(1449543736, 1), "optimeDate" : ISODate("2015-12-08T03:02:16Z"), "electionTime" : Timestamp(1449541974, 1), "electionDate" : ISODate("2015-12-08T02:32:54Z"), "self" : true }, { "_id" : 3, "name" : "10.10.10.252:10003", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 2154, "lastHeartbeat" : ISODate("2015-12-08T03:06:08Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T03:06:09Z"), "pingMs" : 0 }, { "_id" : 4, "name" : "10.10.10.252:10004", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 233, "optime" : Timestamp(1449543736, 1), "optimeDate" : ISODate("2015-12-08T03:02:16Z"), "lastHeartbeat" : ISODate("2015-12-08T03:06:08Z"), "lastHeartbeatRecv" : ISODate("2015-12-08T03:06:08Z"), "pingMs" : 0, "syncingTo" : "10.10.10.252:10002" } ], "ok" : 1 }
可以看到启动成功了
副本集是强大!!!!配置如此简单。