MongoDB中local.replset.minvalid集合的作用

明儼發表於2016-12-09

在mongodb副本集的local庫中,有一個replset.minvalid集合,這個集合正常情況下會記錄一個OpTime,包含時間戳(ts)欄位和選舉任期(t,如果使用的v1選舉協議)。有時候會有一些額外的欄位,如『begin』、『doingInitialSync:true』等,如下,摘抄自mongodb程式碼註釋:

 * { _id:...,
 *      doingInitialSync: true // initial sync is active
 *      ts:..., t:...   // end-OpTime
 *      begin: {ts:..., t:...} // a batch is currently being applied, and not consistent
 * }
 

那這個集合是幹什麼用的呢?簡單來說這個集合是Secondary節點用來標識當前是否處於一個一致狀態。當節點已經應用到了這個集合中的OpTime對應的oplog,那麼它是一致的。具體地看,這個集合主要有如下幾個作用:

  1. 標記當前正在執行initial sync。在initial sync開始時,會在這個集合中寫入一個『doingInitialSync:true』的標記,結束後清除。如果initial sync過程中程式crash了,下次重啟的時候會根據這個標記重新進行initial sync。
  2. 保證Secondary節點在同步過程能原子性的應用一批oplog(即要麼全部應用,要麼全部不應用)。在Secondary節點同步的過程中,拉取了一批oplog後準備應用時,會在這個集合中寫入這批oplog的時間戳區間。即將集合的OpTime更新成這批oplog的結束OpTime,另外再增加一個『begin』欄位標識這批oplog的起始時間戳。當這一批oplog被成功應用完畢後,會將這個『begin』欄位移除。如果在一批oplog應用途中程式crash了,下次重啟時會通過『begin』欄位檢測到這是一次不完整的batch apply oplog操作,會將oplog截斷到『begin』欄位標識的OpTime之前,以將已應用的部分oplog刪除掉。之所以要這麼做是因為因為Secondary在apply一批oplog的時候是併發進行的,當中可能產生一些中間狀態,需要保證全部apply完畢後才能對外可見。
  3. 如果Secondary節點在選擇同步源的時候發現自己已經落後太多,已經跟不上其他節點,也會修改minvalid集合,將缺失的oplog時間區間(從自己的最新一條oplog的時間戳到看到的其他節點最舊的oplog時間戳)寫到minvalid集合中,並進入維護模式,變為RECOVERING狀態。從RECOVERING狀態重新回到Secondary狀態時也會檢查是否已應用完了minvalid集合中記錄的OpTime對應的oplog。
  4. 此外,當節點需要回滾(rollback)時,在回滾之前會獲取minvalid集合的資料進行判斷當前節點是否處於一致的狀態,如果不是則直接assert結束程式。在回滾過程中,會在這個集合中記錄當前同步源節點的最新的oplog的OpTime,以標識當前處於不一致狀態,等到回滾結束後,由同步執行緒追上這個oplog後清除。回滾過程可參加MongoDB副本集回滾那些事


相關文章