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