您的位置:首页 > 数据库 > Mongodb

mongodb复制和分片

2016-08-13 22:01 204 查看

复制

主从复制

主从复制是MongoDB最常用的复制方式,这种方式非常灵活,可用于备份、故障恢复、读扩展等。
最基本的设置方式就是建立一个主节点和一个或者多个从节点,每个从节点要知道主节点的地址。运行mongod --master就启动了主服务器。运行mongod --slave --source master_address则启动了从服务器,其中master_address 就是上面主节点的地址。
**选项**
主从复制有些有用的选项。


–only

在从节点上指定只复制特定某个数据库(默认复制所有数据库)

–slavedelay

用在从节点上,当应用主节点的操作时增加延时(单位是秒)。这样就能设置延时从节点了,这种节点对用户无意中删除重要文档或者插入垃圾数据等事故时有很重要的防护作用。这些不良操作都会被复制到所有从节点上,通过延缓执行操作,可以有个时间差。

–fastsync

主节点的数据快照为基础启动从节点,如果数据目录一开始是主节点的数据快照,从节点用这个选项启动要比完整同步快很多。

–autoresync

如果从节点与主节点不同步了,则自动重新同步。

–oplogSize

主节点oplog的大小(单位是MB)。

添加及删除源

启动从节点时可以用–source指定主节点,也可以在shell中配置这个源。

启动从节点时,不绑定源,而是随后向sources集合添加主节点信息。

C:\Users\Administrator>mongod --dbpath dbs/slave2 --slave --port 27018


在shell中运行如下命令,将localhost:27017作为源添加到从节点上:

MongoDB Enterprise > use local
switched to db local
MongoDB Enterprise > db.sources.insert({"host": "localhost:27017"})
WriteResult({ "nInserted" : 1 })


当在从数据库中查询时,报错

MongoDB Enterprise > show dbs
2016-08-13T19:14:18.412+0800 E QUERY    [thread1] Error: listDatabases failed:{
"ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:761:19
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1


这是正常的,因为从数据库是不允许读写的,如果非要读写,可以运行以下命令

MongoDB Enterprise > rs.slaveOk()
MongoDB Enterprise > show dbs
local  0.000GB
pxh    0.000GB


副本集

副本集就是有自动故障恢复功能的主从集群。主从集群和副本集最为明显的区别就是副本集没有固定的”主节点”:整个集群会选举出一个”主节点”,当其不能工作则变更到其他节点。然而,二者看上去非常相似:副本集总会有一个活跃节点和一个或多个备份节点。

副本集所有东西都是自动化的。首先,它做了很多管理工作,自动提升备份节点成为活跃节点。其次,它对与开发者而言,也很易用:仅需要为副本集指定一下服务器,驱动程序就会自动找到服务器,在当前活跃节点死机时自动处理故障恢复这类事情。

初始化副本集

先从最简单的例子开始:两个服务器。

不能用localhost地址作为成员,得用机器的主机名。

首先,要为每个服务器创建数据目录,选择端口:

D:\Program Files\MongoDB\dbs>md node1

D:\Program Files\MongoDB\dbs>md nodee

D:\Program Files\MongoDB\dbs>md node2


在启动之前,还得给副本集起个名字。名字是为了易于与别的副本集区分,也是为了方便的将整个集合视为一个整体。这里就命名为”blort”.

之后就启动服务器。–replSet是个没接触过的选项,作用是让服务器知晓在这个”blort”副本集中还有别的同伴,位置在CZ-205106ZC:10002还没启动呢

D:\Program Files\MongoDB>mongod --dbpath dbs/node1 --port 10001 --replSet  blort/CZ-205106ZC:10002


以同样的方式启动另一台:

D:\Program Files\MongoDB>mongod --dbpath dbs/node2 --port 10002 --replSet blort/CZ-205106ZC:10001


如果想添加第3台,下面两种方式都行:

D:\Program Files\MongoDB>mongod --dbpath dbs/n
4000
ode3 --port 10003 --replSet blort/CZ-205106ZC:10001


D:\Program Files\MongoDB>mongod --dbpath dbs/node3 --port 10003 --replSet blort/CZ-205106ZC:10001,CZ-205106ZC:10002


副本集有自动检测功能:在指定单台服务器后,MongoDB就会自动搜索并连接其余的节点。

启动几台服务器之后,日志就会告诉你副本集没有进行初始化。因为还差最后一步:在shell中初始化副本集。

在shell,连接其中一个服务器。初始化命令只能执行一次:

C:\Users\Administrator>mongo CZ-205106ZC:10001/admin
2016-08-13T22:30:29.175+0800 I CONTROL  [main] Hotfix KB2731284 or later update
is not installed, will zero-out data files
MongoDB shell version: 3.2.8
connecting to: CZ-205106ZC:10001/admin
MongoDB Enterprise > db.runCommand({"replSetInitiate" : {
... "_id" : "blort",
... "members": [
...  {
...    "_id" : 1,
...    "host": "CZ-205106ZC:10001"
...  },
... {
...    "_id": 2,
...    "host": "CZ-205106ZC:10002"
... }
... ]}})
{ "ok" : 1 }


查看日志可以看到那一台被选为活跃节点:

2016-08-13T22:35:35.570+0800 I REPL     [ReplicationExecutor] Member CZ-205106ZC:10002 is now in state SECONDARY


2016-08-13T22:35:44.772+0800 I REPL     [ReplicationExecutor] Member CZ-205106ZC:10001 is now in state PRIMARY


副本集中的节点

任何时间,集群只有一个活跃节点,其他的都为备份节点,活跃节点实际上是活跃服务器,这里不同的是, 指定的活跃节点可以随时间而改变。

有几种不同类型的节点可以存在于副本集中。

standard

这种就是常规节点,它存储一份完整的数据副本,参与选举投票,有可能成为活跃节点。

passive

存储了完整的数据副本,参与投票,不能成为活跃节点。

arbiter

仲裁者只参与投票,不接收复制的数据,也不能成为活跃节点。

标准节点和被动节点的区别仅仅就是数量的差别;每个参与节点(非仲裁者)有个优先权。优先权为0则是被动的,不能成为活跃节点。优先值一样的话看谁的数据比较新。所以,要是有两个优先值为1和一个优先值为0.5的节点,最后一个节点只有在前两个节点都不可用的时候才能成为活跃节点。

在节点配置中修改property键,来配置成标准节点或者被动节点。

ongoDB Enterprise blort:PRIMARY> db.system.replset.update({"_id" : "blort"},
.. {$push: {"members": {
.. "_id" : 3,
.. "host": "CZ-205106ZC:10003",
.. "priority": 40
.. }}})
riteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })


默认优先级为1,可以使0~100

“arbiterOnly”键可以指定仲裁节点

MongoDB Enterprise blort:PRIMARY> db.system.replset.find()
{ "_id" : "blort", "version" : 1, "protocolVersion" : NumberLong(1), "members" : [ { "_id" : 1, "host" : "CZ-205106ZC:10001", "*arbiterOnly*" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" :NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "CZ-205106ZC:10002", "*arbiterOnly*" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 3, "host" : "CZ-205106ZC:10003", "priority" : 40 } ], "settings" : { "chainingAllowed" :true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "getLastErrorModes" : {  }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("57af302f2e581e0a2842372a") }
}


备份节点会从活跃节点抽取oplog,并执行操作,就像活跃备份系统中的备份服务器一样。oplog中的操作也包括严格递增的序号。通过这个序号来判定数据的时效性。(注: oplog活跃节点的操作记录operation log的简写)

故障切换和活跃节点选举

如果活跃节点坏了,其余节点会选出一个新的活跃节点出来。选举过程可以由任何非活跃节点发起。新的活跃节点由副本集中的大多数选举产生。仲裁节点也会参与投票,避免出现僵局(比如,当网络分割,参与节点被分成两半时)。新的活跃节点将是优先级最高的节点,优先级相同则数据较新的节点获胜。

活跃节点使用心跳来跟踪集群中有多少节点对其可见,如果不够半数,活跃节点自动降为备份节点。这样就能防止活跃节点一直不放权,比如当网络分割后已经与集群隔离开的时候。

不论活跃节点何时变化,新活跃节点的数据就被假定为系统的最新数据。对其他节点(即原来的活跃节点)的操作都会回滚,即便是之前的活跃节点已经恢复工作了。为了完成回滚,所有节点连接新的活跃节点后要重新同步。这些节点会查看自己的oplog,找出其中活跃节点没有执行过的操作,然后向活跃节点请求这些操作影响的文档的最新副本。正在执行重新同步的节点被视为恢复中,在完成这个过程之前不能成为活跃节点候选者。

在从服务器上执行操作

从节点的主要作用为故障恢复机制,以防主节点数据丢失或者停止业务。但是还有些别的用法,从节点可用做备份的数据源,也可以用来扩展性能,或是进行数据处理。

读扩展

用MongoDB扩展读取的一种方式就是将查询放在从节点上。这样,主节点的负载就减轻了。适合读取密集型的解决方案,要是写入密集型,可以使用分片来扩展。

使用从节点扩展MongoDB的读取有个要点,就是数据复制并不同步。也就是说在主节点插入和更新数据后,有片刻从节点的数据不是最新的。

扩展读本身很简单,还像往常一样设置主从复制,连接从服务器处理请求。唯一的技巧就是有个特殊的查询选项,告诉从服务器是否可以处理请求,这个选项是slaveOkay,所有的MongoDB驱动程序都提供了一种机制来设置它。

用从节点做数据处理

从节点的另外一个用途就是作为一种机制来减轻密集型处理的负载,或作为聚合,避免影响主节点的性能。用–master参数启动一个普通的从节点。同时使用–master 和–slave 有点矛盾。这意味着如果能对从节点进行写入、像往常一样查询,就把它当作一个普通的主节点。从节点还是会不断地从主节点复制数据。这样,就可以对从节点执行阻塞操作而不影响主节点的性能。(注意: 不能对正在复制主节点数据的从节点的数据库执行写入操作,从节点不能恢复这些操作,就不能正确地映射主节点。)

工作原理

MongoDB复制至少有两个服务器或者两个节点,一个主节点,负责处理客户端请求,其他都是从节点,负责映射主节点的数据。主节点记录在其上执行的所有操作(不包括不改变数据库数据的操作,如查询操作),从节点定期轮询主节点获得这些操作,然后对自己的数据副本执行这些操作。与主节点数据同步。

oplog

主节点的操作记录成为oplog,oplog存储在一个特殊数据库中,叫做local。oplog就在其中oplog.$main的集合里面。oplog中的每个文档都代表主节点执行的一个操作。

ts

操作的时间戳。时间戳是一种内部数据类型,用于跟踪操作执行的时间。由4字节的时间戳和4字节的递增计数器构成。

op

操作类型,只有1字节代码。(例如”i”代表插入)

ns

执行操作的命名空间(集合名)

o

进一步指定要执行的操作的文档。对插入来说,就是要插入的文档。

从节点中存储在oplog中的操作也不是完全和主节点的一模一样,这些操作在存储之前,先要做等幂变换,也就是说,这些操作可以在服务器端多次执行,只要顺序是对的,就不会又问题。例如,使用”inc"执行的增加更新操作,会被转换成“set”操作。

oplog存在固定集合里面,这样就能保证oplog不超过预先设定的大小。启动服务器时,可以用–oplogSize 指定这个大小,单位是MB。默认情况下,64位的实例使用oplog5%的可用空间。

复制

从节点第一次启动时,会对主节点进行完整的同步,从节点复制主节点的每个文档,耗费的资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: