MongoDB的复制一:复制的原理


1.复制的角色
复制有三种角色:
primay:主库,执行所有的写操作,并把日志写入oplog里。
secondary:复制主库的所有操作。读取主库的oplog,并执行日志里的内容。默认情况下,客户端不能读取secondary的数据。
arbiter:仲裁者,在主库失败后选举主库。该角色是可选的角色。仲裁者不包含数据,客户端不可连接。

2.主库
primay:主库,执行所有的读写操作,并 把日志 写入oplog里。

3.备库
secondary:复制主库的所有操作。读取主库的oplog,并执行日志里的内容。在主库宕机后,备库可以切换为主库
备库可做以下配置:
1)设置成priority 0的备库,使其不能成为主库。其它特性不变。
2)设置成应该程序不能访问
3)做主库的延迟快照。即延迟复制。延迟的备库必须是priority 0的,并且应该设置为hidden.

3.仲裁者
不包含数据,只负责极少工作,对机器的要求低,可以放在性能差一点的机器上。
每个arbiter可以投一票。 其实,每个主库备库都可以投一票
注意:不能在主库或者备库上建仲裁者.(不是不能建,但是会影响投票的准确性)。只在节点数为偶然的集群中加入仲裁者。


4.关于容灾
节点数与可以宕机的节点的个数(否则会产生选举不出primary的问题):

(foolr(N/2)+1) 至少一半成员状态正常,否则不能选举出primary(待验证)
关于选举:
http://www.itpub.net/thread-1740982-1-1.html

三台机器的两种复制形式:


3.其它细节
心跳:节点之间每2秒检查心跳,如果一个节点10秒内没有响应就认为该节点失效。
优先级:各节点都有优先级,优先级越高的备库越有希望成为转换为主库
无选举权节点:一个复制群最多可以有50个节点,但是只有7个有选举权,剩下的没有选举权但是可以复制数据

4.回滚
“回滚”:如果备库没有跟上主库的节奏,而主库又挂了,选举了新的主库,之前的主库又加入到复制群中做为备库,
此时之前 的主库会做回滚操作。
MongoDB会把回滚数据写入到rollback/目录下,dba来决定是忽视还是使用这些数据。

避免回滚:
默认情况下 write concern {w: 1}  确保主库写完后就返回给client,可以改成 w: majority  ,大多数据写完后返回结果给客户端。但显示可能增加响应时间。

回滚的限制:
默认下,只能回滚300M以内的数据,如果大于300M,日志中有以一警告:
[replica set sync] replSet syncThread: 13410 replSet too much data to roll back  
此时必须“ save the data directly ”(语义不明),或者执行初始化。执行初始化同步,必须删除--dbpaht目录下的内容。。。
详情略。

5.设置默认的 write concern

 
    
  1.   db.products.insert(
  2.                         { writeConcern: { w: 2, wtimeout: 5000 } } #至少写入一个从结点
  3.                      )
  4. { w: "majority", wtimeout: 5000 }  

6.设置复制的可读性
默认下,应用只能读主库。
详情略。

7.oplog的大小
默认以5%的磁盘空间做oplog。 详情略。

8.数据同步
有两种方式数据同步:initial sync和Replication

initical sync:初始化数据。
当集群新增加了成员,新成员没有数据,从开始复制数据。
过程如下 :
1)从数据源复制所有数据库,只复制有效的数据。这个步骤中,_id上的索引也被建立。从3.0开始如果发现无效数据,将会在日志中记录: Cloner: found corrupt document in <collection> .
2)使用oplog同步数据。
3)在各集合上建立索引

replication:复制,即正常的数据同步。
支持多线程复制数据。


9.master-slave 复制
mongodb的复制分为两种。旧的称为master-slave复制,没有自动failover功能。新的称为replication sets,有 自动 failover功能。
这时介绍master-slave复制。
创建master:
mongod --master --dbpath /data/masterdb/ 
创建salve:
mongod  -- slave  -- source  < masterhostname ><:< port >> -- dbpath  / data / slavedb / 
这样就创建了一个主备。

配置mster-slave:
slave上,master的信息保存在此处:
use local
db.sources.find()#包含了source信息.
db.sources.insert( { host: <masterhostname> <,onlydatabasename} );  

slave 无法同步数据
slave无法同步数据的原因: 备库的复制进度落后太远了。
一旦备库的复制进度落后主库太完,复制就会中断。
解决办法:
必须执行resync命令重新同步数据(应该是initical sync,即重0数据开始同步)。如果在启动slave时加上--autoresync,则slave在复制中断10秒后自动执行resync。
为了避免这种情况,在master启动的时候,可以设置--oplogSize参数,设置较大的日志文件。默认使用磁盘的5%做为oplog,32位上最小是50M,64位上最小1G.

运行时检查配置情况:
2.6以前,在master执行 db.printReplicationInfo() local库。2.6以后,执行rs. printReplicationInfo().
2.6以前,在slave执行 db.printSlaveReplicationInfo() local库。2.6以后,执行rs. printSlaveReplicationInfo ().

安全性:
如果master启用了authorization,需要配置keyfile,slave通过keyfile与master通信。
在config文件里加入:
keyFile=/usr/local/mongo/  keyfile
keyFile的内容在各个节点上必须一样。可以使用OpenSSL来生成一个keyfile.

master-slave的failover:
master-slave的角色切换:
从master的磁盘快照创建slave:
从slave的磁盘快照创建slave:
resync复制进度过慢(无法继续复制)的salve:
 
     
  1. use admin
  2. db.runCommand( { resync: 1 } )  
修改slave的配置信息然后重启slave:
 
    
  1. use local
  2. db.sources.update( { host : "prod.mississippi" },
  3. { $set : { host : "prod.mississippi.example.net" } } )

10. replication sets


配置replication sets
1)以--replSet启动mongod
 mongod --replSet "rs0"  -f /usr/local/mongodb-linux-x86_64-3.2.0/mongodb.conf 
2)进入mong shell
>mongo
3)初始化复制集(没有配置信息)
 
    
  1. > rs.initiate();
  2. {
  3. "info2" : "no configuration specified. Using a default configuration for the set",
  4. "me" : "node1:27017",
  5. "ok" : 0,
  6. "errmsg" : "No host described in new configuration 1 for replica set repl0 maps to this node",
  7. "code" : 93
  8. }
4)验证初始配置
 
    
  1. > rs.conf();
  2. 2015-12-27T11:04:15.763+0800 E QUERY [thread1] Error: Could not retrieve replica set config: {
  3. "info" : "run rs.initiate(...) if not yet done for the set",
  4. "ok" : 0,
  5. "errmsg" : "no replset config has been received",
  6. "code" : 94
  7. } :
  8. rs.conf@src/mongo/shell/utils.js:1090:11
  9. @(shell):1:1
  10. > cfg={"_id":"rs0","version":1,"members":[{"_id":1,"host":"192.168.75.10:27017"}]};
  11. {
  12. "_id" : "rs0",
  13. "version" : 1,
  14. "members" : [
  15. {
  16. "_id" : 1,
  17. "host" : "192.168.75.10:27017"
  18. }
  19. ]
  20. }
  21. > rs.initiate(cfg);
  22. { "ok" : 1 }

5)在复制集中加入节点
 
    
  1. rs0:PRIMARY> rs.add("192.168.75.11:27017");
  2. { "ok" : 1 }
  3. rs0:PRIMARY> rs.add("192.168.75.12:27017");
  4. { "ok" : 1 }
6)检查复制集状态
 
    
  1. rs0:PRIMARY> rs.status();
  2. {
  3. "set" : "rs0",
  4. "date" : ISODate("2015-12-27T03:13:26.970Z"),
  5. "myState" : 1,
  6. "term" : NumberLong(1),
  7. "heartbeatIntervalMillis" : NumberLong(2000),
  8. "members" : [
  9. {
  10. "_id" : 1,
  11. "name" : "192.168.75.10:27017",
  12. "health" : 1,
  13. "state" : 1,
  14. "stateStr" : "PRIMARY",
  15. "uptime" : 575,
  16. "optime" : {
  17. "ts" : Timestamp(1451185968, 1),
  18. "t" : NumberLong(1)
  19. },
  20. "optimeDate" : ISODate("2015-12-27T03:12:48Z"),
  21. "electionTime" : Timestamp(1451185613, 2),
  22. "electionDate" : ISODate("2015-12-27T03:06:53Z"),
  23. "configVersion" : 3,
  24. "self" : true
  25. },
  26. {
  27. "_id" : 2,
  28. "name" : "192.168.75.11:27017",
  29. "health" : 1,
  30. "state" : 2,
  31. "stateStr" : "SECONDARY",
  32. "uptime" : 41,
  33. "optime" : {
  34. "ts" : Timestamp(1451185968, 1),
  35. "t" : NumberLong(1)
  36. },
  37. "optimeDate" : ISODate("2015-12-27T03:12:48Z"),
  38. "lastHeartbeat" : ISODate("2015-12-27T03:13:24.973Z"),
  39. "lastHeartbeatRecv" : ISODate("2015-12-27T03:13:26.011Z"),
  40. "pingMs" : NumberLong(1),
  41. "syncingTo" : "192.168.75.10:27017",
  42. "configVersion" : 3
  43. },
  44. {
  45. "_id" : 3,
  46. "name" : "192.168.75.12:27017",
  47. "health" : 1,
  48. "state" : 2,
  49. "stateStr" : "SECONDARY",
  50. "uptime" : 37,
  51. "optime" : {
  52. "ts" : Timestamp(1451185968, 1),
  53. "t" : NumberLong(1)
  54. },
  55. "optimeDate" : ISODate("2015-12-27T03:12:48Z"),
  56. "lastHeartbeat" : ISODate("2015-12-27T03:13:25.028Z"),
  57. "lastHeartbeatRecv" : ISODate("2015-12-27T03:13:25.128Z"),
  58. "pingMs" : NumberLong(1),
  59. "configVersion" : 3
  60. }
  61. ],
  62. "ok" : 1
  63. }

7) 测试复制情况:
 
    
  1. rs0:PRIMARY> use testdb
  2. switched to db testdb
  3. rs0:PRIMARY> db.test1231.insert({"name":"test repl"});
  4. WriteResult({ "nInserted" : 1 })
 
     
  1. rs0:SECONDARY> rs.slaveOk();
  2. rs0:SECONDARY> use testdb
  3. switched to db testdb
  4. rs0:SECONDARY> show collections;
  5. test1231
  6. rs0:SECONDARY> db.test1231.find();
  7. { "_id" : ObjectId("567f58f221cb21ff2f187d33"), "name" : "test repl" }

节点重新同步resync:
如果一个节点没有数据,将该结点加入到replication set中,则会自动的完全同步数据。
把一个有数据的结点加入到replication set中:清除--dbpath目录中的内容重启该实例即可。

8)replication set的一些设置
参照:
 
    
  1. 设置优先级,是否隐藏及延时
  2. cfg = rs.conf()
  3. cfg.members[0].priority = 0
  4. cfg.members[0].hidden = true
  5. cfg.members[0].slaveDelay = 3600
  6. rs.reconfig(cfg)
 
     
  1. 设置选举权:
  2. cfg = rs.conf()
  3. cfg.members[3].votes = 0
  4. cfg.members[4].votes = 0
  5. cfg.members[5].votes = 0
  6. rs.reconfig(cfg)















转载于:https://www.cnblogs.com/skyrim/p/5098167.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值