當前位置:
首頁 > 知識 > MongoDB複製集全量同步改進

MongoDB複製集全量同步改進

MongoDB副本集數據同步方式

intial sync,可以理解為全量同步。

replication,追同步源的oplog,可以理解為增量同步。

下面會詳細介紹MongoDB數據同步的實現原理。

initial sync

Secondary節點當出現如下狀況時,需要先進行全量同步。

oplog為空。

local.replset.minvalid集合里_initialSyncFlag欄位設置為true。

內存標記initialSyncRequested設置為true。

這3個場景分別對應

新節點加入,無任何oplog,此時需先進性initial sync。 initial sync開始時,會主動將_initialSyncFlag欄位設置為true,正常結束後再設置為false;如果節點重啟時,發現_initialSyncFlag為true,說明上次全量同步中途失敗了,此時應該重新進行initial sync。 當用戶發送resync命令時,initialSyncRequested會設置為true,此時會重新開始一次initial sync。

intial sync流程

全量同步開始,設置minvalid集合的_initialSyncFlag。 獲取同步源上最新oplog時間戳為t1。 全量同步集合數據 (耗時)。 獲取同步源上最新oplog時間戳為t2。 重放[t1, t2]範圍內的所有oplog。 獲取同步源上最新oplog時間戳為t3。 重放[t2, t3]範圍內所有的oplog。 建立集合所有索引 (耗時)。 獲取同步源上最新oplog時間戳為t4。 重放[t3, t4]範圍內所有的oplog。 全量同步結束,清除minvalid集合的_initialSyncFlag。

Replication

initial sync結束後,接下來Secondary就會『不斷拉取主上新產生的oplog並重放』,這個過程在Secondary同步慢問題分析也介紹過,這裡從另一個角度再分析下。

producer thread,這個線程不斷的從同步源上拉取oplog,並加入到一個BlockQueue的隊列里保存著。

replBatcher thread,這個線程負責逐個從producer thread的隊列里取出oplog,並放到自己維護的隊列里。

sync線程將replBatcher thread的隊列分發到默認16個replWriter線程,由replWriter thread來最終重放每條oplog。

問題來了,為什麼一個簡單的『拉取oplog並重放』的動作要搞得這麼複雜?

性能考慮,拉取oplog是單線程進行,如果把重放也放到拉取的線程里,同步勢必會很慢;所以設計上producer thread只干一件事。

為什麼不將拉取的oplog直接分發給replWriter thread,而要多一個replBatcher線程來中轉?

oplog重放時,要保持順序性,而且遇到createCollection、dropCollection等DDL命令時,這些命令與其他的增刪改查命令是不能並行執行的,而這些控制就是由replBatcher來完成的。

注意事項

initial sync單線程複製數據,效率比較低,生產環境應該盡量避免initial sync出現,需合理配置oplog,按默認『5%的可用磁碟空間』來配置oplog在絕大部分場景下都能滿足需求,特殊的case(case1, case2)可根據實際情況設置更大的oplog。

新加入節點時,可以通過物理複製的方式來避免initial sync,將Primary上的dbpath拷貝到新的節點,直接啟動,這樣效率更高。

當Secondary上需要的oplog在同步源上已經滾掉時,Secondary的同步將無法正常進行,會進入RECOVERING的狀態,需向Secondary主動發送resyc命令重新同步。3.2版本目前有個bug,可能導致resync不能正常工作,必須強制(kill -9)重啟節點,詳情參考SERVER-24773。

生產環境,最好通過db.printSlaveReplicationInfo()來監控主備同步滯後的情況,當Secondary落後太多時,要及時調查清楚原因。

當Secondary同步滯後是因為主上並發寫入太高導致,(db.serverStatus().metrics.repl.buffer.sizeBytes持續接近db.serverStatus().metrics.repl.buffer.maxSizeBytes),可通過調整Secondary上replWriter並發線程數來提升。

MongoDB 3.4複製集全量同步改進

MongoDB 3.2版本複製集同步的過程參考上面,在MongoDB 3.4版本里MongoDB對複製集同步的全量同步階段做了2個改進:

在拷貝數據的時候同時建立所有的索引,在之前的版本里,拷貝數據時會先建立_id索引,其餘的索引在數據拷貝完之後集中建立。

在拷貝數據的同時,會把同步源上新產生的oplog拉取到本地local資料庫的臨時集合存儲著,等數據全量拷貝完,直接讀取本地臨時集合的oplog來應用,提升了追增量的效率,同時也避免了同步源上oplog不足導致無法同步的問題。

上圖描述了這2個改進的效果,實測了『10GB的數據,包含64個集合,每個集合包含2個索引欄位,文檔平均1KB,3.4版本的全量同步性能約有20%的提升,如果數據集很大,並且在同步的過程中有寫入,提升的效果會更明顯,並且徹底解決了因同步源oplog不足而導致進入RECOVERING狀態無法同步的問題。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 尤沐西子 的精彩文章:

Linux查看分區文件系統類型的幾種方法
黑客如何破解密碼?

TAG:尤沐西子 |