您好,登錄后才能下訂單哦!
MongoDB副本集(Replica Set)是一組MongoDB實例組成的集群,由一個主節(jié)點(primary)和多個備節(jié)點(Secondary)組成。通過Repication,將數(shù)據(jù)的更新由primary推送到其他備
節(jié)點上。每個MongoDB實例維護相同的數(shù)據(jù)集副本,通過維護冗余的數(shù)據(jù)集副本,能夠?qū)崿F(xiàn)數(shù)據(jù)的異地備份,讀寫分離和自動故障轉(zhuǎn)移。
拓?fù)浣Y(jié)構(gòu):
創(chuàng)建一個Replica set,包含三個成員,一個primary和兩個secondary成員,primary處理客戶端請求,secondary用于保存primary數(shù)據(jù)副本。客戶端在primary進行讀寫操作,通過
replication的異步同步機制,將數(shù)據(jù)操作同步sencondary成員,保證三個成員擁有相同的數(shù)據(jù)集。
如果primary連接中斷超過10s,其他節(jié)點會自動選舉出一個primary節(jié)點,負(fù)責(zé)響應(yīng)客戶端的請求,實現(xiàn)數(shù)據(jù)的自動故障轉(zhuǎn)移。
技術(shù)原理說明:
mongodb instance有兩種不同的啟動方式,一種是以單實例啟動(standalone),一種是副本集(replica set)模式,如果設(shè)置replSet參數(shù),mongodb實例將以副本集模式啟動。
選舉primary成員:
在Replica Set中有兩種成員:Primary成員和Secondary成員,一個Replica Set只能有一個Primary成員,但可以有多個Secondary成員。Primary用于處理客戶端請求,Secondary用于保存Primary的數(shù)據(jù)副本。如果Primary崩潰了,Replica Set探測到Primary不可訪問,將啟動自動故障轉(zhuǎn)移進程,從剩下的Secondary成員中,投票選舉出一個成員作為Primary,接收和處理客戶端的請求。
選舉Primary成員時,使用“大多數(shù)”和“一票否決”原則。在Replica Set中,每個成員只能要求自己被選舉為Primary節(jié)點。當(dāng)一個Secondary成員無法與Primary成員連通時,該成員就會發(fā)起選舉,請求其他成員將自己選舉為Primary成員,只有得到“大多數(shù)”成員的支持,該成員才能被選舉為Primary成員;只要有一個成員否決,選舉就會取消。
不是每一個成員都有投票選舉的權(quán)利,在一個Replica Set中,最多有7個成員用于投票選舉的權(quán)利,Primary成員是由這7個成員選舉出來的。有投票權(quán)利的成員,其屬性:"votes" 是1;若為0,表示該成員沒有投票權(quán)利。
操作日志:
mongodb使用操作日志(oplog)來實現(xiàn)復(fù)制(replication)功能。oplog包含了primary節(jié)點的每一個更新操作,通過oplog傳遞到其他secondary節(jié)點中,在其他節(jié)點重做(redo)已經(jīng)提交的操作,實現(xiàn)數(shù)據(jù)的異步同步。每個成員維護著自己的oplog,記錄著每一個從primary節(jié)點復(fù)制過來的數(shù)據(jù)。
復(fù)制過程是先復(fù)制數(shù)據(jù),再寫oplog中。如果因為重啟導(dǎo)致執(zhí)行重復(fù)操作,將oplog中同一個操作執(zhí)行多次,與執(zhí)行一次的結(jié)果是一樣的。
oplog保存的是對每個doc的更新操作日志,如果一個命令只更新一個doc,那么Replication進程向oplog插入一條日志;如果一個命令更新多個doc,那么Replication進程向oplog插入多條日志,每一條日志只更新一個doc。
配置文件參數(shù)定義:
replSet:設(shè)置Replica Set的name,在各個配置文件中,其值必須相同
dbpath:MongoDB用于存儲數(shù)據(jù)的目錄
logpath:用于記錄mongod的日志數(shù)據(jù)
port:指定MongoDB監(jiān)聽的端口,默認(rèn)值是27017
創(chuàng)建配置文檔,調(diào)用rs.initiate()函數(shù),按照配置文檔來初始化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數(shù)組指定 Replica Set的成員的ID 和 host(“host:port”)
1、修改Replica Set
如果以rs.initiate()方式初始化Replica Set,那么MongoDB以默認(rèn)配置文檔初始化Replica Set,可以通過add()函數(shù)增加成員
2、向Replica Set中增加一個成員
rs.add("host:port")
3、從Replica Set中刪除一個成員
rs.remove("host")
4、查看Replica Set的配置
rs.conf()
5、查看Replica Set的狀態(tài)
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字段唯一標(biāo)識一個Replica Set,每一個Replica Set都有一個自增的版本號,由Version字段標(biāo)識,標(biāo)識Replica Set的不同版本。version字段的初始值是1,每次修改Replica Set的配置時,version字段都會自增.
arbiterOnly:0或1,標(biāo)識一個仲裁(arbiter),Arbiter的唯一作用是參與Primary的選舉,Arbiter不保存數(shù)據(jù),不會為client提供服務(wù),它存在的意義就是為了選舉Primary.
hidden:0或1,表示該成員是不是隱藏成員,Hidden成員的主要作用是備份數(shù)據(jù),可以使用性能較差的服務(wù)器作為Hidden成員。Hidden成員不會接收Client的請求,也不會成為Primary。在設(shè)置Hidden成員時,必須設(shè)置members[n].priorty屬性為0.
priority:數(shù)值類型,用于設(shè)置成員成為Primary的優(yōu)先級。priority越高的成員,越有機會成為Primary。如果priority=0,那么該成員永遠(yuǎn)不會成為Primary.
votes:1或0,表示該成員的投票的數(shù)量,在每個Replica Set中,最多有7個成員,其votes屬性值是1。votes 屬性是1的成員(voting members)擁有選舉Primary的權(quán)利。一個成員要想成為一個Primary,那么必須獲得voting members的大多成員的支持.
在Replica Set中,如果voting members的數(shù)量是5,那么一個成員成為Primary的條件是:獲得超過2個voting members的支持,并且沒有任何voting members 反對。只要有任意一個voting member 反對該成員成為Primary,那么該成員就不能成為Primary。
在客戶端查看進程信息:
shard1:PRIMARY> db.serverCmdLineOpts()
命令含義:
rs.:副本命令,是replSet是縮寫,代表副本集
db.:數(shù)據(jù)庫命令,比如db.printReplicationInfo(),db.printSlaveReplicationInfo()
rs.status:查看成員的復(fù)制狀態(tài),可以在任意節(jié)點執(zhí)行
rs.config():可以得到當(dāng)前副本的配置,修改配置文件,然后將修改后的配置文件傳遞給reconfig、initiate命令
rs.reconfig()(replSetReconfig):修改副本集的配置。rs.reconfig(conf,{"force":true})
rs.initiate():會初始化配置,只需要對副本集中的一個成員調(diào)用rs.initiate就可以(一般主節(jié)點),收到initiate命令的成員會自動將配置文件傳遞給副本集中的其他成員
修改副本集成員配置時的限制:
1、不能修改_id;
2、不能將當(dāng)前執(zhí)行rs.reconfig命令的成員的優(yōu)先級設(shè)置為 0;
3、不能將仲裁者成員變?yōu)榉侵俨谜叱蓡T,反正亦然;
4、不能將buildIndexes由false改為 true;
強制重新配置:
在備份節(jié)點上調(diào)用rs.reconfig(conf,{"force":ture})強制重新配置副本集。注意conf必須是正確、有效的配置。而且只允許在備份節(jié)點執(zhí)行強制重新配置。
查看復(fù)制源
查詢節(jié)點從哪個節(jié)點處復(fù)制。在備份節(jié)點上運行,也可以運行rs.status(),查看"syncingTo"字段信息.
db.adminCommand({"replSetGetStatus":1})['syncingTo'];
復(fù)制鏈:
MongoDB根據(jù)ping時間選擇同步源,一個成員向另一個成員發(fā)送心跳請求,就知道心跳請求所耗費的時間(rs.status()中的"pingMs"記錄了成員到達相關(guān)成員的所花費的平均時間)。MongosDB維護著不同成員間請求的平均花費時間。選擇同步源時,會選擇一個離自己比較近而且數(shù)據(jù)比自己新的成員。但是同一數(shù)據(jù)中心的成員可能會從同一數(shù)據(jù)中心的其他成員處復(fù)制,而不是從位于另一個數(shù)據(jù)中心的主節(jié)點處復(fù)制(這樣可以減少網(wǎng)絡(luò)流量),所以會出現(xiàn)復(fù)制鏈的情況,復(fù)制鏈越長會導(dǎo)致主節(jié)點的操作復(fù)制到所有的服務(wù)器所花費的時間越長。這對于需要從副本中讀取數(shù)據(jù)的需求這種情況是不希望看到的。
修改復(fù)制源
db.adminCommand({"replSetSyncFrom":"192.168.137.10:27011"});
禁用復(fù)制鏈(在主副本中執(zhí)行)
conf = rs.conf()
conf.settings.chainingAllowed = false
rs.reconfig(conf)
計算延遲:
查看當(dāng)前副本集oplog狀態(tài)
rs.printReplicationInfo()
configured oplog size:oplog配置的大小
log length start to end: oplog包含的操作時長。
oplog first event time: oplog第一條操作的時間。
oplog last event time: oplog最后一條操作的時間。
now:當(dāng)前時間。
注意:oplog中第一條操作與最后一條操作的時間差就是操作日志的長度。
查看復(fù)制延遲,會顯示當(dāng)前所有的備份節(jié)點同步時間,和落后主節(jié)點的時長:
rs.printSlaveReplicationInfo()
調(diào)整oplog大?。?/p>
1) 如果是主節(jié)點,將主節(jié)點變成備份節(jié)點。
2) 將oplog中的最后一條insert操作保存到其它集合中。
use local
db.tempLastOp20180330.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )
3) 關(guān)閉當(dāng)前服務(wù)
4) 以單機模式啟動,可以指定一個新的端口,或者將replSet注釋掉已配置文件啟動
mongod --port 6777 --bind_ip 192.168.10.10,127.0.0.1 --dbpath /u02/mongo6777/data/
5) 刪除當(dāng)前oplog
db.oplog.rs.drop();
6) 創(chuàng)建新的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) 以副本成員身份啟動當(dāng)前服務(wù)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。