一、主从集群

MongoDB支持在多个机器中通过异步复制达到故障转移和实现冗余。多机器中同一个时刻只有一台是用于写操作。正是由于这个情况,为MongoDB提供了数据一致性的保障。担当Primary角色的机器能把读操作分发给slave。

MongoDB的主从集群分为两种:

Master-Slave复制(主从) ---------不建议使用了!!!

Replica Sets复制(副本集)



Master-Slave复制

只需要在某一个服务启动时加上-master参数,而另一个服务加上-slave与-source参数,即可实现同步。

MongoDB的最新版本已经不推荐使用这种方法了。因为主服务器宕机了,从服务器不会自动变成主!

mongodb 副本集提升主 mongodb主从复制和副本集_数据库

主:端口为20000

[root@localhost mongodb]# mkdir data1 data2
[root@localhost mongodb]# touch dblog1.log
[root@localhost mongodb]# touch dblog2.log
[root@localhost mongodb]# /usr/local/mongodb/bin/mongod --master --dbpath=/usr/local/mongodb/data1/ --logpath=/usr/local/mongodb/dblog1.log --fork --port 20000
about to fork child process, waiting until server is ready for connections.
forked process: 4837
child process started successfully, parent exiting
[root@localhost mongodb]# netstat -tunpl |grep 20000 【查看端口】
tcp        0      0 127.0.0.1:20000         0.0.0.0:*               LISTEN      4837/mongod         
[root@localhost mongodb]#

连接Mongo客户端:

[root@localhost mongodb]# /usr/local/mongodb/bin/mongo --port 20000

#在master插入一条数据,在slave中是可以看到的
> db.c1.insert({name:"user1",age:1});

从:端口为20001 (可以在另一窗口中处理)

[root@localhost mongodb]# /usr/local/mongodb/bin/mongod --slave --source 127.0.0.1:20000 --dbpath=/usr/local/mongodb/data2/ --logpath=/usr/local/mongodb/dblog2.log --fork --port 20001
about to fork child process, waiting until server is ready for connections.
forked process: 4868
child process started successfully, parent exiting

[root@localhost mongodb]# netstat -tunpl |grep :20001
tcp        0      0 127.0.0.1:20001         0.0.0.0:*               LISTEN      4868/mongod         
[root@localhost mongodb]#

连接Mongo客户端:

一个错误的解决:

[root@localhost mongodb]# /usr/local/mongodb/bin/mongo --port 20001

>rs.slaveOk(); ###确认一下自己是从!!
>db.c1.find(); ##可以看到master中刚才插入的数据!

##在slave中插入式不会成功的!
> db.c1.insert({name:"user2"});
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })


###在从上备份貌似不太好使!!注意一下!!!
[root@localhost bin]# ./mongodump --port 20001 -d test
2018-05-27T06:04:15.672-0400	Failed: error connecting to db server: no reachable servers
[root@localhost bin]# ./mongodump --port 20000 -d test
2018-05-27T06:04:25.309-0400	writing test.c1 to 
2018-05-27T06:04:25.310-0400	done dumping test.c1 (1 document)
[root@localhost bin]#



Replica Sets复制(副本集)

MongoDB在1.6版本开发了replica set,主要增加了故障自动切换和自动修复成员节点,各个DB之间数据完全一致,最为显著的区别在于,副本集没有固定的主节点,它是整个集群选举得一个主节点,当其不工作时变更为其他节点!

mongodb 副本集提升主 mongodb主从复制和副本集_python_02

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。

mongodb各个节点常见的搭配方式为:一主一从、一主多从。

主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

MongoDB复制结构图如下所示:

mongodb 副本集提升主 mongodb主从复制和副本集_python_03

以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。



副本集特征:

  • N 个节点的集群
  • 任何节点可作为主节点
  • 所有写入操作都在主节点上
  • 自动故障转移
  • 自动恢复
#《1.》创建数据文件存储路径
[root@localhost mongodb]# mkdir -p data/data1
[root@localhost mongodb]# mkdir -p data/data2
#《2.》创建日志文件
[root@localhost mongodb]# mkdir log
[root@localhost mongodb]# touch log/dblog1.log
[root@localhost mongodb]# touch log/dblog2.log

#《3.》创建主从key文件用于标识集群的私钥的完整路径
#如果各个实例的key file的内容不一致,将不能正常通信!
[root@localhost mongodb]# mkdir key
[root@localhost mongodb]# touch key/key1
[root@localhost mongodb]# touch key/key2
[root@localhost mongodb]# echo "123456">key/key1
[root@localhost mongodb]# echo "123456">key/key2
[root@localhost mongodb]# chmod 600 key/*


#《4.》####启动实例1#####
[root@localhost mongodb]# /usr/local/mongodb/bin/mongod --replSet rs1 --keyFile=/usr/local/mongodb/key/key1 --port=20001 --dbpath=/usr/local/mongodb/data/data1/ --logpath=/usr/local/mongodb/log/dblog1.log --fork
about to fork child process, waiting until server is ready for connections.
forked process: 5062
child process started successfully, parent exiting
[root@localhost mongodb]# netstat -tunpl |grep :20001
tcp        0      0 127.0.0.1:20001         0.0.0.0:*               LISTEN      5062/mongod 


#《5》######启动实例2##########
[root@localhost mongodb]# /usr/local/mongodb/bin/mongod --replSet rs1 --keyFile=/usr/local/mongodb/key/key2 --port=20002 --dbpath=/usr/local/mongodb/data/data2/ --logpath=/usr/local/mongodb/log/dblog2.log --fork
about to fork child process, waiting until server is ready for connections.
forked process: 5093
child process started successfully, parent exiting
[root@localhost mongodb]# netstat -tunpl |
> grep 2000
tcp        0      0 127.0.0.1:20001         0.0.0.0:*               LISTEN      5062/mongod         
tcp        0      0 127.0.0.1:20002         0.0.0.0:*               LISTEN      5093/mongod    


#《6.》配置Replica Sets####
[root@localhost mongodb]# /usr/local/mongodb/bin/mongo --port 20001
> config_rs1={
... _id:"rs1",
... members:[
... {_id:0,host:"127.0.0.1:20001",priority:1},
... {_id:1,host:"127.0.0.1:20002",priority:2}
... ]}
{
	"_id" : "rs1",
	"members" : [
		{
			"_id" : 0,
			"host" : "127.0.0.1:20001",
			"priority" : 1
		},
		{
			"_id" : 1,
			"host" : "127.0.0.1:20002",
			"priority" : 2
		}
	]
}
> 

##《7.》初始化Replica Sets#####
> rs.initiate(config_rs1);
{
	"ok" : 1,
	"operationTime" : Timestamp(1527418399, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1527418399, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
>

客户端登录情况:

主:

#如果插入数据或show tables:没有权限,要加权限!此处要再看看!!3.0以后的版本权限控制更严格了!!
rs1:PRIMARY> db.createUser({user:"dba",pwd:"dba",roles:["userAdminAnyDatabase","readWriteAnyDatabase","dbAdminAnyDatabase"]});
rs1:PRIMARY> db.auth("dba","dba");

##插入值
rs1:PRIMARY> db.c1.insert({name:"user1"});

从:

##从库可以查到
>rs.slaveOk(); ##需要的!!!

rs1:SECONDARY> db.c1.find();
{ "_id" : ObjectId("5b0a914f0a5056c858949b1b"), "name" : "user1" }


###从库并不能插入成功
rs1:SECONDARY> db.c1.insert({name:"user2"});
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })