8、java程序连接副本集测试。三个节点有一个节点挂掉也不会影响应用程序客户端对整个副本集的读写!

public class TestMongoDBReplSet {

 

        public static void main(String[] args) {

 

               try {

                     List addresses = new ArrayList();

                     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副本集的读写分离如何做呢?


看图说话:


mongorep5


常规写操作来说并没有读操作多,所以一台主节点负责写,两台副本节点负责读。


1、设置读写分离需要先在副本节点SECONDARY 设置 setSlaveOk。

2、在程序中设置副本节点负责读操作,如下代码:


public class TestMongoDBReplSetReadSplit {

 

        public static void main(String[] args) {

 

               try {

                     List addresses = new ArrayList();

                     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早就有了相应的解决方案。


看图:

mongorep7


其中的仲裁节点不存储数据,只是负责故障转移的群体投票,这样就少了数据复制的压力。是不是想得很周到啊,一看mongodb的开发兄弟熟知大数据架构体系,其实不只是主节点、副本节点、仲裁节点,还有Secondary-Only、Hidden、Delayed、Non-Voting。


Secondary-Only:不能成为primary节点,只能作为secondary副本节点,防止一些性能不高的节点成为主节点。

Hidden:这类节点是不能够被客户端制定IP引用,也不能被设置为主节点,但是可以投票,一般用于备份数据。

Delayed:可以指定一个时间延迟从primary节点同步数据。主要用于备份数据,如果实时同步,误删除数据马上同步到从节点,恢复又恢复不了。

Non-Voting:没有选举权的secondary节点,纯粹的备份数据节点。


到此整个mongodb副本集搞定了两个问题:


主节点挂了能否自动切换连接?目前需要手工切换。

主节点的读写压力过大如何解决?

还有这两个问题后续解决:


从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大?

数据压力大到机器支撑不了的时候能否做到自动扩展?

做了副本集发现又一些问题:


副本集故障转移,主节点是如何选举的?能否手动干涉下架某一台主节点。

官方说副本集数量最好是奇数,为什么?

mongodb副本集是如何同步的?如果同步不及时会出现什么情况?会不会出现不一致性?

mongodb的故障转移会不会无故自动发生?什么条件会触发?频繁触发可能会带来系统负载加重