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)
















免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM