"syncingTo" : "192.168.1.137:27017"
}
],
"ok" : 1
}
再启动原来的主节点 138,发现138 变为 SECONDARY,还是137 为主节点 PRIMARY。
| 1 2 3 4 5 6 7 8 |
Sun Dec 29 22:21:06.619 [rsStart] replSet I am 192.168.1.138:27017 Sun Dec 29 22:21:06.619 [rsStart] replSet STARTUP2 Sun Dec 29 22:21:06.627 [rsHealthPoll] replset info 192.168.1.136:27017 thinks that we are down Sun Dec 29 22:21:06.627 [rsHealthPoll] replSet member 192.168.1.136:27017 is up Sun Dec 29 22:21:06.627 [rsHealthPoll] replSet member 192.168.1.136:27017 is now in state SECONDARY Sun Dec 29 22:21:07.628 [rsSync] replSet SECONDARY Sun Dec 29 22:21:08.623 [rsHealthPoll] replSet member 192.168.1.137:27017 is up Sun Dec 29 22:21:08.624 [rsHealthPoll] replSet member 192.168.1.137:27017 is now in state PRIMARY |
8、java程序连接副本集测试。三个节点有一个节点挂掉也不会影响应用程序客户端对整个副本集的读写!
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class TestMongoDBReplSet {
public static void main(String[] args) {
try { List ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017); ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017); ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017); addresses.add(address1); addresses.add(address2); addresses.add(address3);
MongoClient client = new MongoClient(addresses); DB db = client.getDB( "test"); DBCollection coll = db.getCollection( "testdb");
// 插入 BasicDBObject object = new BasicDBObject(); object.append( "test2", "testval2" );
coll.insert(object);
DBCursor dbCursor = coll.find();
while (dbCursor.hasNext()) { DBObject dbObject = dbCursor.next(); System. out.println(dbObject.toString()); }
} catch (Exception e) { e.printStackTrace(); }
}
} |
目前看起来支持完美的故障转移了,这个架构是不是比较完美了?其实还有很多地方可以优化,比如开头的第二个问题:主节点的读写压力过大如何解决?常见的解决方案是读写分离,mongodb副本集的读写分离如何做呢?
看图说话:

常规写操作来说并没有读操作多,所以一台主节点负责写,两台副本节点负责读。
1、设置读写分离需要先在副本节点SECONDARY 设置 setSlaveOk。
2、在程序中设置副本节点负责读操作,如下代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class TestMongoDBReplSetReadSplit {
public static void main(String[] args) {
try { List ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017); ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017); ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017); addresses.add(address1); addresses.add(address2); addresses.add(address3);
MongoClient client = new MongoClient(addresses); DB db = client.getDB( "test" ); DBCollection coll = db.getCollection( "testdb" );
BasicDBObject object = new BasicDBObject(); object.append( "test2" , "testval2" );
//读操作从副本节点读取 ReadPreference preference = ReadPreference. secondary(); DBObject dbObject = coll.findOne(object, null , preference);
System. out .println(dbObject);
} catch (Exception e) { e.printStackTrace(); } } } |
读参数除了secondary一共还有五个参数:primary、primaryPreferred、secondary、secondaryPreferred、nearest。

primary:默认参数,只从主节点上进行读取操作;
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
好,读写分离做好我们可以数据分流,减轻压力解决了“主节点的读写压力过大如何解决?”这个问题。不过当我们的副本节点增多时,主节点的复制压力会加大有什么办法解决吗?mongodb早就有了相应的解决方案。
看图: