MongoDB副本集回滾那些事

2021-09-23 17:58:13 字數 3459 閱讀 2358

回滾(rollback)操作是mongodb副本集發生一些異常主備切換後可能發生的現象。回滾操作會撤銷在當前節點上已執行的一些修改操作。

mongodb副本集節點上有個同步執行緒,負責拉取需要同步的oplog。被拉取oplog的節點稱作同步源。那麼,要回滾,首先要有乙個同步源。

鏈式複製

平時我們都說主備同步主備同步,那同步源肯定是主節點了?其實不一定,mongodb很早就支援了鏈式複製,即備節點可以從另外乙個備節點拉取oplog,而不只從主節點拉取。這樣一來可以減少主節點的負載,二來各節點可以選擇離自己近的節點進行同步。當然,在某些情況下,這可能會導致一些備節點的延遲變大。鏈式複製可以通過以下命令來開啟或關閉:

cfg = rs.config()

cfg.settings.chainingallowed = true/false

rs.reconfig(cfg)

secondary節點如何選擇同步源

secondary節點會根據以下原則選擇乙個同步源:

如果之前有通過命令replsetsyncfrom指定了同步源,那麼使用此同步源

由於後續需要根據到其他節點的ping值(通過心跳進行統計)資訊進行選擇,這裡會判斷一下是否已有足夠的資訊,需要等待更多的心跳包,如果不需要,繼續,否則直接返回,等下次需要選擇時再看

如果沒有開啟chained replication(鏈式複製),那麼選擇primary

通過兩輪選擇,基於以下規則選擇乙個ping值最低的節點:

如果自己可以建索引,那麼只能從同樣可以建索引的節點同步

不在黑名單中(注:何時將同步節點加進黑名單?1. 連線不上該節點,加10s黑名單;2. 落後該節點太多無法繼續同步,加1min黑名單)

其中在第一輪選擇中,會額外考慮以下條件:

擁有投票權的節點只能從同樣擁有投票權的節點同步

不能從hidden節點同步

不能從落後primary太多(超過配置的maxsyncsourcelagsecs)的節點同步

不能從配置了比自己擁有更大delay的節點同步

如果第一輪沒有選出合適的節點,那麼再進行第二輪選擇,放寬上述條件的限制。

回到回滾觸發條件。同步執行緒已經選擇出了乙個同步源,它向同步源發起乙個find請求,查詢大於等於其最新的oplog時間戳的oplog。如果發生以下兩種情況,那麼需要回滾:

在同步源上沒有查到比其更新的oplog(我們剛剛通過一系列麻煩的規則選出它作為同步源,但是我們的oplog卻比它還新)

返回的的第一條oplog和其最新的oplog的optime和hash都不同,注意這裡是比較整個optime,即除了時間戳之外還包括term,首先會比較term,如果term不同,那就不同

回滾之前會獲取minvalid集合的資料進行判斷當前節點是否處於一致的狀態,如果不是則直接assert結束程序。關於minvalid集合的作用,可參見mongodb中local.replset.minvalid集合的作用。如果允許進行回滾,則執行以下步驟:

記錄日誌『rollback 0』

進入rollback狀態

記錄日誌『rollback 1』

向同步源傳送乙個replsetgetrbid的命令獲取乙個rollbackid,這個rollbackid是用來在後面判斷在rollback過程中同步源自身是否發生回滾,每個節點如果發生rollback,會修改自己的rollbackid。

記錄日誌『rollback 2 findcommonpoint』

查詢自己和同步源的oplog的commonpoint,這裡是從同步源最新的oplog開始逆向查詢,比較自己和同步源的最新的oplog的時間,計算相差的秒數,如果超過30分鐘,那麼放棄rollback;如果本地的oplog時間戳比對方的更新,往前繼續找,直到找到時間戳相等的那條。這裡每比較一條本地的oplog,都會對oplog的內容進行解析,從而得到回滾所需執行的操作集(包括需要重新從同步源獲取的文件、需要重新同步的集合、需要drop的集合、索引等。這裡同時也會進行一些判斷,如果有發現某條oplog的大小大於512mb,放棄回滾。如果有dropdatabase操作,放棄回滾。)。找到了時間戳相等且hash一致的oplog,就找到了commonpoint。

記錄日誌『rollback 3 fixup』

自增rollbackid

接下來根據剛剛解析oplog得到的需要重新從同步源獲取其最新版本的文件集,從同步源逐個獲取,並儲存在乙個map中。這裡會對要回滾的資料總大小進行判斷,不能超過300mb。所有文件處理完畢後,從同步源獲取其最新的oplog的時間備用

記錄日誌『rollback 3.5』

再次獲取同步源的rollbackid,如果和剛剛得到的不一樣,那說明同步源自身也發生了回滾,放棄這次回滾操作

記錄日誌『rollback 4 n:需要更新的文件個數』

將剛才第9步從同步源得到的最新的oplog的時間戳作為結束時間,插入乙個時間戳區間到minvalid集合,表明當前資料處於不一致狀態。

如果有需要重新同步整個集合資料或元資料的的,逐個處理(重新同步集合資料的,先drop然後copycollection;重新同步集合元資料的,獲取元資料並更新到本地),此處會記錄日誌『rollback 4.1.1 coll resync』或『rollback 4.1.2 coll metadata resync』。這裡由於可能比較費時,記錄日誌『rollback 4.2』,然後再一次獲取同步源最新的oplog時間戳記錄到minvalid集合,並再次判斷同步源是否自身發生回滾。如果一切正常,記錄日誌『rollback 4.3』。

記錄日誌『rollback 4.6』

處理需要drop的集合(如果有),這裡會做collscan將要drop的集合的文件的內容寫到rollback目錄裡的檔案中

處理需要drop的索引(如果有)

記錄日誌『rollback 4.7』

處理剛剛從同步源獲取的最新版本的文件集,先將本地的文件寫到rollback目錄裡的檔案中,然後刪除或更新

記錄日誌『rollback 5 d:刪除的文件數 u:更新的文件數』

記錄日誌『rollback 6』

清除本地oplog集合中在commonpoint之後的oplog

reload本地的最新oplog

記錄日誌『rollback done』

再次自增自己的rollbackid

記錄日誌『rollback finished』

需要注意的是,當執行完最後一步記錄日誌『rollback finished』,其實回滾還沒真正結束。此時節點會進入recovering狀態,minvalid集合中還記錄了乙個時間戳區間。即節點在回滾過程中記錄了需要同步到哪個optime,後續等同步執行緒追上這個時間點後才能變成secondary狀態。如果在這時候,發生了同步源切換,比如切換到另外乙個同樣需要回滾的節點,並且又將剛剛已清除掉的commonpoint之後的oplog給同步回來,那麼就可能觸發第二次回滾觸發assert退出。關於這個bug,mongodb官方已在3.2.11版本中修復server-25145,修復方法是在選擇同步源的時候增加是否包含minvalid中optime的判斷。我們阿里雲資料庫mongodb也已merge了這個bugfix。

mysql副本集 MongoDB副本集

一 節點型別standard 常規節點,它儲存乙份完整的資料副本,參與選舉投票,有可能成為活躍節點。passive 儲存了完整的資料副本 一 節點型別 standard 常規節點,它儲存乙份完整的資料副本,參與選舉投票,有可能成為活躍節點。passive 儲存了完整的資料副本,參與投票,不能成為活躍...

mysql副本集 mongoDB副本集的搭建

環境簡介 192.168.1.151 fedoraserver 用作副本集的主庫,已經有資料 192.168.1.152 fedoraserver 從庫,空例項 192.168.1.153 fedoraserver 從庫,空例項 mongodb的副本集和mysql基於gtid的多源三例項迴圈主從即 ...

mongodb 系統 副本集

mongodb 系統 副本集 rm r data f mkdir data mkdir data mongodb data mkdir data mongodb log chown r richy data mongodb data chown r richy data mongodb log re...