MongoDB 复制

1.主从复制

主从复制是MongoDB最常用的复制方式。这种复制方式非常灵活,可用于备份、故障恢复、读扩展等。

通过启动时的选项进行设置,每个从节点要知道主节点的地址,所有从节点都从主节点复制内容,目前还没有能够从从节点复制的机制,原因是从节点并不保存自己的oplog。

相关的启动选项

--master  设置当前服务为主节点
--slave   设置当前服务为从节点
--source  指定主节点的地址
--only    在从节点上指定只复制特定某个数据库(默认复制除local之外的所有数据库)
--slavedelay  设置从节点复制主节点时的延时
--fastsync    以主节点的数据快照为基础启动从节点
--autoresync  如果从节点和主节点不同步了,则自动重新同步
--oplogsize   主节点oplog的大小

e.g.

//启动主节点
mongod --dbpath D:\mongoDB\master --logpath D:\mongoDB\master-log\log.log --master --port 10000
//启动从节点
mongod --dbpath D:\mongoDB\slave --logpath D:\mongoDB\slave-log\log.log --slave --source localhost:10000 --port 10001

/* 测试 */
//连接主节点
mongo --host localhost --port 10000
use test;
db.user.insert({"id": "001", "name": "路人甲0"});

//连接从节点
mongo --host localhost --port 10001
use test;
db.user.find();

1)添加或删除源

启动从节点时可以用source选项指定主节点,也可以再shell中配置。

主从节点关系相关集合

--主节点:local库slaves

--从节点:local库sources

删除源:需要同时删除主节点和从节点相关集合中的记录

添加源:从节点中相关集合新增记录即可,主节点会自动添加记录,e.g.

use local;
db.sources.insert({"host": "localhost:10000"});

也可以实现主节点的切换或者一个从节点对应多个不同的主节点。

注:如果不同的主节点有相同的集合,MongoDB会尝试合并,但是不保证正确合并。

2)工作原理

--MongoDB的复制至少需要两个节点。一个是主节点,其它的为从节点。

--主节点负责处理客户端请求,记录在其上执行的所有操作

--从节点负责映射主节点的数据,通过轮询主节点的oplog,然后对自己的数据副本执行这些操作实现

3)oplog

主节点的操作记录,operation log,简称oplog,存储在local库oplog.$main集合中。e.g.

{ "ts" : Timestamp(1395202153, 1), "op" : "i", "ns" : "test.user", "o" : { "_id" : ObjectId("5329186953152d9334a80347"), "id" : "001", "name" : "路人甲0" } }

ts:操作的时间戳
op:操作类型
ns:操作的命名空间
o:执行操作的文档

--oplog只记录改变数据库状态的操作

--oplog在存储前需要做等幂变换,即这些操作可以在服务器端多次执行,只要顺序是对的,就不会有问题

--oplog存储在固定集合中,默认大小为剩余磁盘空间的5%

4)同步

从节点第一次启动时,会对主节点数据进行完整的同步。同步完成后,从节点开始查询主节点的oplog并执行这些操作,以保证数据时最新的。

当从节点跟不上同步时(oplog已经滚了一圈了),复制就会停下,从节点需要重新做完整的同步。

--手动同步

use admin;
db.runCommand({"resync": 1});

--自动同步:使用autoresync选项启动从节点

注:完整同步代价高昂,应该调整oplog的大小尽量避免。

5)阻塞复制

使主节点进入阻塞状态,直到N个服务器复制了最新的写入操作为止。

db.runCommand({"getLastError": 1, "w": ..., "wtimeout": ...});
w:节点个数,包含主节点本身
wtimeout:以毫秒为单位的超时
e.g.
db.runCommand({"getLastError": 1, "w": 1, "wtimeout": 100});

6)查看复制信息

主节点:db.printReplicationInfo();

从节点:db.printSlaveReplicationInfo();

7)权限校验

当主从节点均以auth选项启动时,需要在主节点和从节点的local库中添加相同用户,才能使从节点能够访问主节点的数据。local中的用户可以读写整个服务器。

从节点连接主节点时,会用存储在local.system.users中的用户进行认证。最先尝试repl用户,若没有此用户,则用local.system.users中的第一个可用用户。e.g.

db.addUser("repl", "repl");

2.副本集

副本集就是有自动故障恢复功能的主从集群。

主从集群和副本集的最大区别是副本集没有固定的主节点:整个集群会选举出一个"主节点",当其不能工作时则变更到其它节点。

1)配置

//启动
mongod --dbpath D:\mongoDB\node1 --logpath D:\mongoDB\node1-log\log.log --replSet test --port 10001

mongod --dbpath D:\mongoDB\node2 --logpath D:\mongoDB\node2-log\log.log --replSet test --port 20002

mongod --dbpath D:\mongoDB\node3 --logpath D:\mongoDB\node3-log\log.log --replSet test --port 30003

//配置
--方法一
db.runCommand({"replSetInitiate": {
	"_id": "test",
	"members": [
		{
			"_id": 1,
			"host": "localhost:10001"
		},
		{
			"_id": 2,
			"host": "localhost:20002"
		},
		{
			"_id": 3,
			"host": "localhost:30003"
		}
	]}
});
--方法二
rs.initiate({
	"_id": "test",
	"members": [
		{
			"_id": 1,
			"host": "localhost:10001"
		},
		{
			"_id": 2,
			"host": "localhost:20002"
		},
		{
			"_id": 3,
			"host": "localhost:30003"
		}
	]});

//查看状态,配置信息存储在local库的system.replset集合中
rs.status();
2)操作

--在PRIMARY上插入数据,在SECONDARY进行查询时出错

error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
解决方法:在SECONDARY上执行下列语句
rs.slaveOk();
--把PRIMARY服务关闭,可发现有一SECONDARY自动调整为PRIMARY --只留一个SECONDARY服务,其余均关闭,发现该SECONDARY无法自动转为PRIMARY 3)节点类型 --standard:常规节点,它存储一份完整的数据副本,参与选举投票,有可能成为活跃节点。 --passive:存储了完整的数据副本,参与投票,不能成为活跃节点。 --arbiter:仲裁节点,只参与投票,不接收复制的数据,也不能成为活跃节点。 4)副本集的相关操作可通过rs.help()进行查看  

猜你喜欢

转载自siyuan-zhu.iteye.com/blog/2033455
今日推荐