首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MongoDB 源碼深度解析:主從複寫模式下 Master 節點核心流程

     編輯:關於C語言

前言:為什麼要讀 MongoDB 複寫源碼?

MongoDB 的複寫機制是其高可用性架構的基石。雖然現代版本(3.0+)已全面推廣 Replica Set(複寫集),但早期的 Master-Slave(主從)模式在架構上更為簡單,適合作為理解複寫核心邏輯的切入點。本文基於 MongoDB 1.6 時代的源碼,深入分析 Master 節點接收寫入操作、生成 oplog、同步至 Slave 的完整流程,並對關鍵資料結構與源碼路徑進行註解。

複寫模式演進回顧

模式特點適用場景
Master-Slave單向同步、手動故障轉移、Slave 可掛多 Master(不推薦)讀寫分離、簡單備份
Replica Pairs雙節點自動協商主從、需 Arbiter 仲裁、支援自動故障轉移雙機高可用
Replica Sets(現代標準)多節點、自動選舉、自動故障轉移、支援仲裁節點生產環境標準部署

Master-Slave 啟動參數詳解

# Master 節點
mongod --dbpath=d:/mongodb/db --master --oplogSize 64

# Slave 節點
mongod --dbpath=d:/mongodb/db --slave --source 10.0.1.103:27017 --only test --slavedelay 100

關鍵參數說明:

  • --oplogSize:指定 oplog 佔用空間(32 位最小 50MB,64 位最小 1GB,上限磁碟 5%)
  • --source:指定 Master 位址(Slave 專用)
  • --only:只同步指定資料庫
  • --slavedelay:同步延遲(秒),防誤刪資料

Oplog(操作日誌)核心資料結構

Oplog 存放於 local.oplog.$main 集合,每份文檔代表一個寫入操作,包含四大欄位:

欄位類型說明
tsTimestamp操作時間戳(4 字節秒數 + 4 字節遞增計數器)
opchar (1 byte)操作類型:'i'=insert, 'u'=update, 'd'=delete, 'n'=noop
nsstring命名空間(資料庫.集合名)
oBSON object操作內容(insert 為文檔本身,update 為修改器,delete 為 _id)

注意: 唯有改變資料庫狀態的操作會記錄 oplog,查詢操作不記錄。

Master 節點核心執行流程源碼分析

入口點:instance.cpp 中的 assembleResponse

// instance.cpp
// Returns false when request includes end
void assembleResponse( Message &m, DbResponse &dbresponse, const SockAddr &client ) {
    ...
    if ( op == dbQuery ) {
        if ( handlePossibleShardedMessage( m , &dbresponse ) )
            return;
        receivedQuery(c , dbresponse, m );
    }
    // 服務端收到 message 執行相關查詢操作
    else if ( op == dbGetMore ) {
        if ( ! receivedGetMore(dbresponse, m, currentOp ) )
            log = true;
    }
    ...
}

這是網路層接收封包後的分發入口。實際寫入操作(insert/update/delete)會走 dbInsert/dbUpdate/dbDelete 分支,最終進入存儲引擎並觸發 oplog 記錄。

Oplog 寫入關鍵路徑

  1. 客戶端發送寫入請求(OP_INSERT / OP_UPDATE / OP_DELETE)
  2. 網路層解析:assembleResponse → receivedInsert/receivedUpdate/receivedDelete
  3. 存儲引擎執行寫入:更新內存數據結構、寫入 journal(若啟用)
  4. 生成 oplog 文檔:構建包含 ts, op, ns, o 的 BSON 物件
  5. 寫入 local.oplog.$main:作為 capped collection,自動淘汰舊記錄
  6. Slave 拉取同步:Slave 定期輪詢 Master 的 oplog,按 ts 順序重放操作

關鍵源碼文件與類別

文件核心職責
db/repl.rs複寫核心邏輯、同步協調、oplog 應用
db/instance.cpp網路請求分發、命令處理入口
db/ops/write_ops.cpp寫入操作實作、oplog 生成觸發點
db/namespace.cpp集合操作、capped collection 管理
db/repl/slave.cppSlave 同步邏輯、oplog 拉取與重放

調試環境搭建建議

  1. 取得 MongoDB 1.6.x 源碼(GitHub 官方倉庫 r1.6 標籤)
  2. 使用 Visual Studio 2010 開啟 mongod.sln
  3. 設定專案屬性 → Debugging → Command Arguments:--master --oplogSize 64
  4. 設定中斷點於 instance.cpp::assembleResponse、write_ops.cpp 寫入路徑
  5. 啟動 Master,再於另一終端啟動 Slave,觀察 oplog 生成與同步過程

從 Master-Slave 到 Replica Sets 的架構啟示

雖然 Master-Slave 已被淘汰,但其核心設計思想延續至今:

  • Write-Ahead Log (WAL) 思想:oplog 本質是邏輯層面的 WAL,保證冪等重放
  • Primary-Backup 模型:單點寫入、多點讀取、非同步複寫
  • 故障檢測與切換:從手動提升 Slave 發展為 Raft 協議自動選舉
  • 一致性層級:從最終一致性演進為可配置的寫入關注

結語

透過閱讀早期 MongoDB 複寫源碼,我們能清晰看到分散式資料庫最核心的問題——「如何在不可靠的網路上維護多副本一致性」——是如何一步步從簡單的主從同步演進為今天成熟的 Replica Set 架構。建議有興趣的讀者進一步研讀 repl.rs 中的同步協調邏輯、slave.cpp 的重放機制,以及現代版本中的 Raft 選舉實作(repl/raft_consensus.cpp)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved