MongoDB 副本集原理及管理

haoge0205發表於2020-08-05

MongoDB副本集(Replica Set)是一組MongoDB例項組成的叢集,由一個主節點(primary)和多個備節點(Secondary)組成。透過Repication,將資料的更新由primary推送到其他備

節點上。每個MongoDB例項維護相同的資料集副本,透過維護冗餘的資料集副本,能夠實現資料的異地備份,讀寫分離和自動故障轉移。

拓撲結構:

建立一個Replica set,包含三個成員,一個primary和兩個secondary成員,primary處理客戶端請求,secondary用於儲存primary資料副本。客戶端在primary進行讀寫操作,透過

replication的非同步同步機制,將資料操作同步sencondary成員,保證三個成員擁有相同的資料集。

如果primary連線中斷超過10s,其他節點會自動選舉出一個primary節點,負責響應客戶端的請求,實現資料的自動故障轉移。

技術原理說明:

mongodb instance有兩種不同的啟動方式,一種是以單例項啟動(standalone),一種是副本集(replica set)模式,如果設定replSet引數,mongodb例項將以副本集模式啟動。

選舉primary成員:

在Replica Set中有兩種成員:Primary成員和Secondary成員,一個Replica Set只能有一個Primary成員,但可以有多個Secondary成員。Primary用於處理客戶端請求,Secondary用於儲存Primary的資料副本。如果Primary崩潰了,Replica Set探測到Primary不可訪問,將啟動自動故障轉移程式,從剩下的Secondary成員中,投票選舉出一個成員作為Primary,接收和處理客戶端的請求。

選舉Primary成員時,使用“大多數”和“一票否決”原則。在Replica Set中,每個成員只能要求自己被選舉為Primary節點。當一個Secondary成員無法與Primary成員連通時,該成員就會發起選舉,請求其他成員將自己選舉為Primary成員,只有得到“大多數”成員的支援,該成員才能被選舉為Primary成員;只要有一個成員否決,選舉就會取消。

不是每一個成員都有投票選舉的權利,在一個Replica Set中,最多有7個成員用於投票選舉的權利,Primary成員是由這7個成員選舉出來的。有投票權利的成員,其屬性:"votes" 是1;若為0,表示該成員沒有投票權利。

操作日誌:

mongodb使用操作日誌(oplog)來實現複製(replication)功能。oplog包含了primary節點的每一個更新操作,透過oplog傳遞到其他secondary節點中,在其他節點重做(redo)已經提交的操作,實現資料的非同步同步。每個成員維護著自己的oplog,記錄著每一個從primary節點複製過來的資料。

複製過程是先複製資料,再寫oplog中。如果因為重啟導致執行重複操作,將oplog中同一個操作執行多次,與執行一次的結果是一樣的。

oplog儲存的是對每個doc的更新操作日誌,如果一個命令只更新一個doc,那麼Replication程式向oplog插入一條日誌;如果一個命令更新多個doc,那麼Replication程式向oplog插入多條日誌,每一條日誌只更新一個doc。

配置檔案引數定義:

replSet:設定Replica Set的name,在各個配置檔案中,其值必須相同

dbpath:MongoDB用於儲存資料的目錄

logpath:用於記錄mongod的日誌資料

port:指定MongoDB監聽的埠,預設值是27017

建立配置文件,呼叫rs.initiate()函式,按照配置文件來初始化Replica Set:

conf=

{

    "_id" : "replname",

    "members" : [

        { "_id" : 0,  "host" : "127.0.0.1:2777"  },

        { "_id" : 1,  "host" : "127.0.0.1:3777"  },

        { "_id" : 2,  "host" : "127.0.0.1:4777"  }

    ]

}

rs.initiate(conf)

使用"_id" : "replname" 指定Replica Set的name

members陣列指定 Replica Set的成員的ID 和 host(“host:port”)

1、修改Replica Set

如果以rs.initiate()方式初始化Replica Set,那麼MongoDB以預設配置文件初始化Replica Set,可以透過add()函式增加成員

2、向Replica Set中增加一個成員

rs.add("host:port")

3、從Replica Set中刪除一個成員

rs.remove("host")

4、檢視Replica Set的配置

rs.conf()

5、檢視Replica Set的狀態

rs.status()

{

"_id" : "replname",

"version" : 7,

"protocolVersion" : NumberLong(1),

"writeConcernMajorityJournalDefault" : true,

"members" : [

{

"_id" : 0,

"host" : "127.0.0.1:2777",

"arbiterOnly" : false,

"buildIndexes" : true,

"hidden" : false,

"priority" : 1,

"tags" : {

},

"slaveDelay" : NumberLong(0),

"votes" : 1

}

Replica Set的ID欄位唯一標識一個Replica Set,每一個Replica Set都有一個自增的版本號,由Version欄位標識,標識Replica Set的不同版本。version欄位的初始值是1,每次修改Replica Set的配置時,version欄位都會自增.

arbiterOnly:0或1,標識一個仲裁(arbiter),Arbiter的唯一作用是參與Primary的選舉,Arbiter不儲存資料,不會為client提供服務,它存在的意義就是為了選舉Primary.

hidden:0或1,表示該成員是不是隱藏成員,Hidden成員的主要作用是備份資料,可以使用效能較差的伺服器作為Hidden成員。Hidden成員不會接收Client的請求,也不會成為Primary。在設定Hidden成員時,必須設定members[n].priorty屬性為0.

priority:數值型別,用於設定成員成為Primary的優先順序。priority越高的成員,越有機會成為Primary。如果priority=0,那麼該成員永遠不會成為Primary.

votes:1或0,表示該成員的投票的數量,在每個Replica Set中,最多有7個成員,其votes屬性值是1。votes 屬性是1的成員(voting members)擁有選舉Primary的權利。一個成員要想成為一個Primary,那麼必須獲得voting members的大多成員的支援.

在Replica Set中,如果voting members的數量是5,那麼一個成員成為Primary的條件是:獲得超過2個voting members的支援,並且沒有任何voting members 反對。只要有任意一個voting member 反對該成員成為Primary,那麼該成員就不能成為Primary。

在客戶端檢視程式資訊:

shard1:PRIMARY> db.serverCmdLineOpts()

命令含義:

rs.:副本命令,是replSet是縮寫,代表副本集

db.:資料庫命令,比如db.printReplicationInfo(),db.printSlaveReplicationInfo()

rs.status:檢視成員的複製狀態,可以在任意節點執行

rs.config():可以得到當前副本的配置,修改配置檔案,然後將修改後的配置檔案傳遞給reconfig、initiate命令

rs.reconfig()(replSetReconfig):修改副本集的配置。rs.reconfig(conf,{"force":true})

rs.initiate():會初始化配置,只需要對副本集中的一個成員呼叫rs.initiate就可以(一般主節點),收到initiate命令的成員會自動將配置檔案傳遞給副本集中的其他成員

修改副本整合員配置時的限制:

1、不能修改_id;

2、不能將當前執行rs.reconfig命令的成員的優先順序設定為 0;

3、不能將仲裁者成員變為非仲裁者成員,反正亦然;

4、不能將buildIndexes由false改為 true;

強制重新配置:

在備份節點上呼叫rs.reconfig(conf,{"force":ture})強制重新配置副本集。注意conf必須是正確、有效的配置。而且只允許在備份節點執行強制重新配置。

檢視複製源

查詢節點從哪個節點處複製。在備份節點上執行,也可以執行rs.status(),檢視"syncingTo"欄位資訊.

db.adminCommand({"replSetGetStatus":1})['syncingTo'];

複製鏈:

MongoDB根據ping時間選擇同步源,一個成員向另一個成員傳送心跳請求,就知道心跳請求所耗費的時間(rs.status()中的"pingMs"記錄了成員到達相關成員的所花費的平均時間)。MongosDB維護著不同成員間請求的平均花費時間。選擇同步源時,會選擇一個離自己比較近而且資料比自己新的成員。但是同一資料中心的成員可能會從同一資料中心的其他成員處複製,而不是從位於另一個資料中心的主節點處複製(這樣可以減少網路流量),所以會出現複製鏈的情況,複製鏈越長會導致主節點的操作複製到所有的伺服器所花費的時間越長。這對於需要從副本中讀取資料的需求這種情況是不希望看到的。

修改複製源

db.adminCommand({"replSetSyncFrom":"192.168.137.10:27011"});

禁用複製鏈(在主副本中執行)

conf = rs.conf()

conf.settings.chainingAllowed = false

rs.reconfig(conf)

計算延遲:

檢視當前副本集oplog狀態

rs.printReplicationInfo()

configured oplog size:oplog配置的大小

log length start to end: oplog包含的操作時長。

oplog first event time: oplog第一條操作的時間。

oplog last event time: oplog最後一條操作的時間。

now:當前時間。

注意:oplog中第一條操作與最後一條操作的時間差就是操作日誌的長度。

檢視複製延遲,會顯示當前所有的備份節點同步時間,和落後主節點的時長:

rs.printSlaveReplicationInfo()

調整oplog大小:

1)  如果是主節點,將主節點變成備份節點。

2)  將oplog中的最後一條insert操作儲存到其它集合中。

use local

db.tempLastOp20180330.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )

3)   關閉當前服務

4)   以單機模式啟動,可以指定一個新的埠,或者將replSet註釋掉已配置檔案啟動

mongod --port 6777 --bind_ip 192.168.10.10,127.0.0.1 --dbpath /u02/mongo6777/data/

5)   刪除當前oplog

db.oplog.rs.drop();

6)   建立新的oplog

db.createCollection("oplog.rs",{"capped":true,"size":1048576})

db.createCollection("oplog.rs",{"capped":true,"size":(2*1024*1024*1024)})

7)  將最後一條insert記錄寫回oplog

var tempLastOp=db.tempLastOp20180330.find().next()

db.oplog.rs.insert(tempLastOp)

db.oplog.rs.find()

8)  以副本成員身份啟動當前服務


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28939273/viewspace-2709568/,如需轉載,請註明出處,否則將追究法律責任。

相關文章