一、MongoDB复制集简介
那什么是复制集呢?而复制集具有多个副本保证了容错性,就算一个副本挂掉了还有很多副本存在,并且解决了上面第一个问题“主节点挂掉了,整个集群内会自动切换”。难怪mongoDB官方推荐使用这种模式。我们来看看mongoDB副本集的架构图:
由图可以看到客户端连接到整个复制集,不关心具体哪一台机器是否挂掉。主服务器负责整个复制集的读写,复制集定期同步数据备份,一但主节点挂掉,副本节点就会选举一个新的主服务器,这一切对于应用服务器不需要关心。我们看一下主服务器挂掉后的架构:
复制集中的副本节点在主节点挂掉后通过心跳机制检测到后,就会在集群内发起主节点的选举机制,自动选举一位新的主服务器。
主节点的读写压力过大如何解决?常见的解决方案是读写分离,mongodb复制集的读写分离如何做呢?
常规写操作来说并没有读操作多,所以一台主节点负责写,两台副本节点负责读。
1、设置读写分离需要先在副本节点SECONDARY 设置 setSlaveOk。
2、在程序中设置副本节点负责读操作,如下代码:
public class TestMongoDBReplSetReadSplit {
public static void main(String[] args) {
try {
List<ServerAddress> addresses = new ArrayList<ServerAddress>();
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早就有了相应的解决方案。
其中的仲裁节点不存储数据,只是负责故障转移的群体投票,这样就少了数据复制的压力。是不是想得很周到啊,一看mongodb的开发兄弟熟知大数据架构体系,其实不只是主节点、副本节点、仲裁节点,还有Hidden、Delayed等节点。
Hidden:这类节点是不能够被客户端制定IP引用,也不能被设置为主节点,但是可以投票,一般用于备份数据。
Delayed:可以指定一个时间延迟从primary节点同步数据。主要用于备份数据,如果实时同步,误删除数据马上同步到从节点,恢复又恢复不了。
到此整个mongodb副本集搞定了两个问题:
- 主节点挂了能否自动切换连接?
- 主节点的读写压力过大如何解决?
还有这两个问题后续解决:
- 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大?
- 数据压力大到机器支撑不了的时候能否做到自动扩展?
做了副本集发现又一些问题:
- 副本集故障转移,主节点是如何选举的?
- 官方说副本集数量最好是奇数,为什么?
- mongodb副本集是如何同步的?如果同步不及时会出现什么情况?会不会出现不一致性?
- mongodb的故障转移会不会无故自动发生?什么条件会触发?频繁触发可能会带来系统负载加重.
参考文献