- 求職 : Linux運(yùn)維
- 論壇徽章:
- 203
|
本帖最后由 lyhabc 于 2016-07-20 17:02 編輯
MongoDB副本集數(shù)據(jù)同步](https://docs.mongodb.com/manual/core/replica-set-sync/)主要包含2個(gè)步驟
intial sync,可以理解為全量同步
replication,追同步源的oplog,可以理解為增量同步
本文是對(duì)MongoDB高可用復(fù)制集原理的補(bǔ)充,會(huì)詳細(xì)介紹MongoDB數(shù)據(jù)同步的實(shí)現(xiàn)原理。
initial sync
Secondary節(jié)點(diǎn)當(dāng)出現(xiàn)如下狀況時(shí),需要先進(jìn)行全量同步
oplog為空
local.replset.minvalid集合里_initialSyncFlag字段設(shè)置為true
內(nèi)存標(biāo)記initialSyncRequested設(shè)置為true
這3個(gè)場(chǎng)景分別對(duì)應(yīng)
新節(jié)點(diǎn)加入,無任何oplog,此時(shí)需先進(jìn)性initial sync
initial sync開始時(shí),會(huì)主動(dòng)將_initialSyncFlag字段設(shè)置為true,正常結(jié)束后再設(shè)置為false;如果節(jié)點(diǎn)重啟時(shí),發(fā)現(xiàn)_initialSyncFlag為true,說明上次全量同步中途失敗了,此時(shí)應(yīng)該重新進(jìn)行initial sync
當(dāng)用戶發(fā)送resync命令時(shí),initialSyncRequested會(huì)設(shè)置為true,此時(shí)會(huì)重新開始一次initial sync
intial sync流程
22222222.jpg (42.61 KB, 下載次數(shù): 43)
下載附件
2016-07-20 17:02 上傳
全量同步開始,設(shè)置minvalid集合的_initialSyncFlag
獲取同步源上最新oplog時(shí)間戳為t1
全量同步集合數(shù)據(jù) (耗時(shí))
獲取同步源上最新oplog時(shí)間戳為t2
重放[t1, t2]范圍內(nèi)的所有oplog
獲取同步源上最新oplog時(shí)間戳為t3
重放[t2, t3]范圍內(nèi)所有的oplog
建立集合所有索引 (耗時(shí))
獲取同步源上最新oplog時(shí)間戳為t4
重放[t3, t4]范圍內(nèi)所有的oplog
全量同步結(jié)束,清除minvalid集合的_initialSyncFlag
Replication
initial sync結(jié)束后,接下來Secondary就會(huì)『不斷拉取主上新產(chǎn)生的oplog并重放『』,這個(gè)過程在Secondary同步慢問題分析也介紹過,這里從另一個(gè)角度再分析下。
producer thread,這個(gè)線程不斷的從同步源上拉取oplog,并加入到一個(gè)BlockQueue的隊(duì)列里保存著。
replBatcher thread,這個(gè)線程負(fù)責(zé)逐個(gè)從producer thread的隊(duì)列里取出oplog,并放到自己維護(hù)的隊(duì)列里。
sync線程將replBatcher thread的隊(duì)列分發(fā)到默認(rèn)16個(gè)replWriter線程,由replWriter thread來最終重放每條oplog。
問題來了,為什么一個(gè)簡(jiǎn)單的『拉取oplog并重放』的動(dòng)作要搞得這么復(fù)雜?
性能考慮,拉取oplog是單線程進(jìn)行,如果把重放也放到拉取的線程里,同步勢(shì)必會(huì)很慢;所以設(shè)計(jì)上producer thread只干一件事。
為什么不將拉取的oplog直接分發(fā)給replWriter thread,而要多一個(gè)replBatcher線程來中轉(zhuǎn)?
oplog重放時(shí),要保持順序性,而且遇到createCollection、dropCollection等DDL命令時(shí),這些命令與其他的增刪改查命令是不能并行執(zhí)行的,而這些控制就是由replBatcher來完成的。
注意事項(xiàng)
initial sync單線程復(fù)制數(shù)據(jù),效率比較低,生產(chǎn)環(huán)境應(yīng)該盡量避免initial sync出現(xiàn),需合理配置oplog,按默認(rèn)『5%的可用磁盤空間』來配置oplog在絕大部分場(chǎng)景下都能滿足需求,特殊的case(case1, case2)可根據(jù)實(shí)際情況設(shè)置更大的oplog。
新加入節(jié)點(diǎn)時(shí),可以通過物理復(fù)制的方式來避免initial sync,將Primary上的dbpath拷貝到新的節(jié)點(diǎn),直接啟動(dòng),這樣效率更高。
當(dāng)Secondary上需要的oplog在同步源上已經(jīng)滾掉時(shí),Secondary的同步將無法正常進(jìn)行,會(huì)進(jìn)入RECOVERING的狀態(tài),需向Secondary主動(dòng)發(fā)送resyc命令重新同步。3.2版本目前有個(gè)bug,可能導(dǎo)致resync不能正常工作,必須強(qiáng)制(kill -9)重啟節(jié)點(diǎn),詳情參考SERVER-24773。
生產(chǎn)環(huán)境,最好通過db.printSlaveReplicationInfo()來監(jiān)控主備同步滯后的情況,當(dāng)Secondary落后太多時(shí),要及時(shí)調(diào)查清楚原因。
當(dāng)Secondary同步滯后是因?yàn)橹魃喜l(fā)寫入太高導(dǎo)致,(db.serverStatus().metrics.repl.buffer.sizeBytes持續(xù)接近db.serverStatus().metrics.repl.buffer.maxSizeBytes),可通過調(diào)整Secondary上replWriter并發(fā)線程數(shù)來提升。 |
|