天天看點

複制集使用及原理介紹

一、MongoDB 副本集概念及建立

(一)MongoDB 副本集的概念

官方概念:副本集是一組 MongoDB 的程序去維持同樣的一份資料集,通過 MongoDB 的複制協定保證主備之間的資料一緻性。

複制集使用及原理介紹

如上圖所示,MongoDB 有兩種部署方式,一個是 Standalone 部署模式,另外一個 是副本級,有不同角色的節點,像 Primary 節點和 Secondary 節點。

生産環境不建議部署 Standalone 模式。

(二)使用 MongoDB 副本集的原因

關鍵詞:可用性、拓展性、維護性

  • 可用性

    額外的副本結合高可用機制提升 MongoDB 執行個體可用性。

  • 擴充性

    通過 Secondary 節點配合 Driver 擴充 MongoDB 執行個體讀能力。

  • 維護性

    通過滾動的方式 MongoDB 執行個體進行維護,盡量減少業務所受到的影響,比如版本升 級與可能會影響使用者流量的 Compact 操作。

複制集使用及原理介紹

(三)MongoDB 副本內建員角色

副本集裡面有多個節點,每個節點擁有不同的職責。

在看成員角色之前,先了解兩個重要屬性:

屬性一:Priority = 0

當 Priority 等于 0 時,它不可以被副本集選舉為主,Priority 的值越高,則被選舉為主 的機率更大。

屬性二:Vote = 0

不可以參與選舉投票,此時該節點的 Priority 也必須為 0,即它也不能被選舉為主。

複制集使用及原理介紹

成員角色

  • Primary:主節點,可以接受讀寫,整個副本集某個時刻隻有一個。
  • Secondary:隻讀節點,分為以下三個不同類型:
    • Hidden = False:正常的隻讀節點,是否可選為主,是否可投票,取決于 Priority,Votes 的值;
    • Hidden = True:隐藏節點,對用戶端不可見,可以參與選舉,但是 Priority 必須為 0,即不能被提升為主;
    • Delayed Secondary:延遲隻讀節點,會延遲一定的時間(SlaveDelay 配置 決定)從上遊複制增量,常用于快速復原場景。
  • Arbiter:仲裁節點,隻用于參與選舉投票,本身不承載任何資料,隻作為投票角色。

(四)如何擷取 MongoDB 副本集

基于工具搭建測試執行個體

目的:業務要做線下測試,需要在本地環境搭建一個副本級或去探索新版本,比如 4.4 新增的功能。

使用工具 Mtools:

基于 mtools 部署副本集,一條指令:

mlaunch init --binarypath '/usr/local/Cellar/mongodb-community/ 4.4.0/bin' --replicaset -nodes 3 --name replset44 --dir ~/work/ mtools_data/data      

執行 Mlaunch,Init 然後指定 Binarypath 還有一些副本集相關參數,Mtools 會一鍵 建立副本集,具體指令執行示範如下:

複制集使用及原理介紹
複制集使用及原理介紹

建立雲上執行個體

  • MongoDB 的運維門檻較高,需要對相關原理有比較深刻的了解,才能運維好 MongoDB 副本集執行個體;
  • 推薦更便捷、可靠的方式:使用 MongoDB 雲服務,一站式的解決方案。阿裡雲 MongoDB 具有社群版不具備的進階功能,如審計日志、按時間點恢複等,詳情如下:
複制集使用及原理介紹

二、MongoDB 副本集使用介紹

(一)MongoDB 副本集連接配接方式

方式一:直接連接配接 Primary 節點,正常情況下可讀寫 MongoDB,但主節點故障切換 後,無法正常通路,如下圖所示。

複制集使用及原理介紹

方式二(強烈推薦):通過高可用 Uri 的方式連接配接 MongoDB,當 Primary 故障切換 後,MongoDB Driver 可自動感覺并把流量路由到新的 Primary 節點,如下圖所示。

複制集使用及原理介紹

參考文檔:

https://help.aliyun.com/document_detail/44623.html

(二)MongoDB 副本集狀态檢視

檢視副本集整體狀态:rs.status()

可檢視各成員目前狀态,包括是否健康,是否在全量同步,心跳資訊,增量同步資訊, 選舉資訊,上一次的心跳時間等。

檢視目前節點角色:DB.IsMaster()

除了目前節點角色資訊,是一個更精簡化的資訊,也傳回整個副本集的成員清單,真正 的 Primary 是誰,協定相關的配置資訊等,Driver 在首次連接配接副本集時會發送該指令。

檢視同步進度/oplog 資訊:rs.printSlaveReplicationInfo()/rs.printReplicationInf

o()

共兩個指令,第一個指令傳回一個彙總的各 Secondary 同步延遲資訊,第二個指令返 回 Oplog 大小、保留時長、 起始時間等資訊。

(三)副本集的基本讀寫

當用用戶端,比如 Mongo Shell,通過 Mongodb Uri 連接配接副本集執行個體,來執行例如 Insert,Find,Delete 等指令,和 Standalone 模式⽆差異,重點看副本集讀寫和 Standalone 比較特異化的地方。

(四)擴充副本集的讀能力 —— ReadPreference

複制集使用及原理介紹

如上圖所示,左邊為一個三節點的副本集,它部署在兩個資料中心,Primary 和其中 一個 Secondary 部署在 Data Center 1,另一個 Secondary 部署在 Data Center 2, 當用預設的 ReadPreference 時,直接讀寫 Primary 節點。如果在 Data Center2 也有 業務程序存在時,也需要讀取 MongoDB 時,則需要用 ReadPreference 模式自動識别 節點的遠近,讀取 Data Center 2 的 Secondary。

ReadPreference 共有以下五種模式:

模式一 Primary

預設模式,直接讀取主節點,更好的一緻性保證

模式二 PrimaryPreferred

主節點不可⽤時,選擇從從節點讀取。

模式三 Secondary 隻從從節點讀取。

模式四 SecondaryPreferred

盡⼒從從節點讀取,如果找不到可⽤的從節點,從主節點讀取。

模式五 Nearest

根據用戶端對節點的 Ping 值判斷節點的遠近,選擇從最近的節點讀取。

ReadPreference(讀偏好)決定了讀請求會通路什角色的節點,合理的 ReadPreference 可以極大地擴充副本集的讀性能,降低通路延遲。

(五)控制寫操作的持久性級别 —— WriteConcern

複制集使用及原理介紹

上圖為 WriteConcern 标準的配置格式,包括三個子參數:

  • W: 決定了寫操作傳回前需要等待多少個副本集節點的确認。
  • J: 決定寫操作産生的日志是否已經落盤。
  • Wtimeout:決定了寫操作等待的逾時時間,避免用戶端一直阻塞。

下面具體示範幾個 WriteConcern 配置的值。

複制集使用及原理介紹

如上圖,當 W:1 時,寫操作在本地執行完成後,直接向用戶端傳回成功,無需等待 日志(Journal)刷盤。

複制集使用及原理介紹

如上圖,當 W:1,J:true 時,差別于 W:1 的主要特點在于寫操作在本地執行完成後, 需要等待日志(Journal)刷盤,會增加額外延遲。

複制集使用及原理介紹

如上圖,當 W: "Majority",當下發了這個寫操作之後,除了需要在 Primary 節點 Apply 完成,還需要複制到其中一個 Secondary 節點去 Apply 完成,才能向 Driver 回報 寫操作成功。

在三節點副本集情況下,"Majority"相當于兩個節點,等同于 W:2。

(六)控制讀操作的一緻性級别 —— ReadConcern

ReadConcern 有五個級别如下:

  • "Local":讀操作直接讀取本地最新送出的資料,傳回的資料可能被復原。
  • "Available":含義和"Local"類似,但是用于 Sharding 場景可能會傳回孤⼉⽂檔。
  • "Majority":讀操作傳回已經在多數節點确認應用完成的資料,傳回的資料不會被復原, 但可能會讀到曆史資料。
  • "Linearizable":讀取最新的資料,且能夠保證資料不會被復原,是所謂的線性一緻性, 是最高的一緻性級别。
  • "Snapshot":隻用于多文檔事務中,和"Majority"語義類似,但額外提供真正的一緻 性快照語義。
複制集使用及原理介紹

上圖為一個三節點副本集,每個 Secondary 節點的複制進度不同,用 Oplog 來表示, 比如 Primary 最新節點寫到 5,第一個 Secondary 節點複制到 x=4,第二個 Secondary 節點複制到 x=3,在不同的 ReadConcern 值下,Client 從不同節點讀的時 候,讀到的是不同版本的資料。

對于 Local 來說,總是讀取最新的資料,Available 也是讀取最新資料,但在分片叢集 場景下兩者不太一樣。

在 Majority 情況下,隻有 x=4 是複制到多數派節點,也就是其中兩個節點。 當用 Majority 讀的時候,在 Primary 上隻能讀到 x=4,在第一個 Secondary 上能讀到 x=4, 但在第二個 Secondary 隻能讀到 x=3。

Linearizable 也比較特殊,隻能在 Primary 節點上使用,是以也能讀取到 x=5,但大 家可能有疑惑,x=5 并沒有複制到多數派節點,MongoDB 的解決方法是,當使用 Linearizable 時,在讀到 x=5 之後,會等 x=5 複制到多數派節點,才會向用戶端傳回成功。

不同 ReadConcern Level 的 Tradeoff

複制集使用及原理介紹

LATEST:能讀到多新的資料;

FAST:能多快地傳回資料;

SAFE:讀的資料是否會發生復原;

Majority:能夠保證 FAST,也就是資料不會被復原。

Linearizable:能夠保證資料不復原,同時讀取最新資料,但犧牲了延遲。 Local/available:能夠最快傳回資料,讀取最新資料,但資料可能會復原。

總結:ReadConcern Level 越高,一緻性保證越好,但通路延遲也更高。

(七)基于副本集的維護性操作舉例 —— Rollover Compact

背景:集合頻繁的插入和删除會導緻“碎片率”上升,浪費存儲空間。

Tips:碎片率計算方式

Https://developer.aliyun.com/article/769536

MongoDB 提供 Compact 指令來回收碎片,但會阻塞讀寫,對業務有影響,在副本 集模式下,滾動的方式來進行 Compact 操作,避免影響業務。

複制集使用及原理介紹

舉個例子,上圖為一個三節點副本集,在最左邊的副本集,使用者可以在 Hidden 節點完 成 Compact Collection 操作。因為 Hidden 對用戶端不可見,因而對業務沒有影響。當 Hidden 節點操作後,可以把 Secondary 節點切換成 Hidden 節點,在新的節點上做 Compact Collection 操作(如上圖中間所示),最後将 Primary 節點也切換成 Hidden 節點(如上圖右邊所示),最終完成 Compact Collection 操作。

切換節點會對業務産生些許影響,但 Driver 能夠自動 Handle,避免直接在 Primary 節點完成 Compact Collection 操作,導緻業務對 DB 不可通路。

三、MongoDB 副本集原理介紹

(一)什麼是 MongoDB Oplog

  • MongoDB Oplog 是 Local 庫下的一個集合,用來儲存寫操作所産生的增量日志(類 似于 MySQL 中的 Binlog);
  • 它是一個 Capped Collection,即超出配置的最大值後,會自動删除最老的曆史資料, MongoDB 針對 Oplog 的删除有特殊優化,以提升删除效率;
  • 主節點産生新的 Oplog Entry,從節點通過複制 Oplog 并應用來保持和主節點的狀态 一緻;
  • Oplog 中包含的有:O —— 插入或更新的内容;Op —— 操作類型;Ns —— 操作 執行的 DB 和集合;Ts —— 操作發生的時間等。
複制集使用及原理介紹

(二)Oplog 保留政策 —— 根據大小及根據時間範圍

  • 4.4 之前
    • 根據 Replication.OplogSizeMB 的配置值決定 Oplog 集合的大小上限,預設為 磁盤空間的 5%,如果使用者是單機多執行個體的部署形态,需要調整預設值;
    • 當 Oplog 集合大小超過上限時,會自動删除最老的 Oplog Entry。
  • 4.4 删除政策增強:MongoDB 提供了按時間段來保留 Oplog,由參數 Storage. OplogMinRetentionHours 控制,友善使用者更好地完成定期維護的操作。
  • 删除時,即使 Oplog 集合大小超過了配置的最⼤值,但最老的 Oplog 仍然在 Storage.OplogMinRetentionHours 範圍内,那麼 Oplog 不會删。

MongoDB 目前提供線上修改 OplogMinRetentionHours 配置值的方式,使用者無需 重新開機執行個體,如下圖所示。

複制集使用及原理介紹

(三)MongoDB 副本集同步原理

MongoDB 副本集同步原理分為兩部分:全量同步與增量同步。

原理一:全量同步

  • 發生時機:
    • 新節點剛加入副本集時
    • 老的節點因為同步滞後而進入 Recovering 狀态時
  • 全量同步包含兩個階段:
    • 資料克隆階段:記錄開始時間 T1,從源端拉取所有的集合資料,不保證資料和源 的一緻性,記錄結束時間 T2;
    • 增量應用階段:應用從 T1 - T2 期間的 Oplog,達到一緻性狀态,全量同步結束。

具體全量同步流程圖如下:

複制集使用及原理介紹

4.4 增強 —— 全量同步斷點續傳 

複制集使用及原理介紹
  • 4.4 之前:全量同步期間,如果發生網絡異常,導緻同步中斷,需要重頭開始,網絡 環境比較差時,大資料量很難完成全量同步,可用節點數變少,執行個體可用性存在隐患;
  • 4.4 : 基于「Resume Token」機制,記錄全量拉取的位點,網絡異常導緻同步中斷 後,重連時帶上 Resume Token;
  • Replication.initialSyncTransientErrorRetryPeriodSeconds 參數決定了同步中斷 後重試的逾時時間,預設 24h。

原理二:增量同步

複制集使用及原理介紹
  • 發生時機:全量同步結束後,持續同步,保持和主節點資料一緻,可以從不同工作職責 的角度分析增量同步的具體流程;
  • Oplog Fetcher 線程負責拉取 Oplog Find 指令建立 Tailable Cursor,GetMore 指令批量從同步源拉取 Oplog,單個 Batch 最大 16MB;
  • 拉取的 Oplog Batch 放到記憶體中的 Blocking Queue 中;
  • ReplBatcher 線程負責從 Blocking Queue 中取出 Batch 生成新的可 Apply 的 Batch 放到 Deque 中,這裡主要是因為需要控制并發,有些操作需要放到一個單獨的 Batch;
  • OplogApplier 線程負責從 Deque 中取出 Batch 寫 Oplog, 然後把 Batch 拆分, 分發到 Worker 線程進行并發 Apply;
  • 為了保持一緻性,中間需要儲存多個不同的 Oplog 應用位點資訊。

(四)MongoDB 副本集高可用原理

複制集使用及原理介紹
  • 主備切換時機:
    • 主節點不可用;
    • 新增節點(更高的 Priority);
    • 主動運維,rs.stepDown() or rs.reconfig()
  • MongoDB 基于 Raft 協定實作了自己的高可用機制;
  • 副本集之間保持心跳(預設 2 秒探測一次);
  • 如果超出 ElectionTimeoutMillis(預設 10 秒)沒有探測到主節點,Secondary 節點 會發起選舉,發起前檢查自身條件:
    • Priority 是否大于 0
    • 目前狀态是否夠新
  • 在真正選舉前,會先進行一輪空投(Dry-Run),避免目前 Primary 無意義的降級( StepDown),因為 Primary 收到其他節點且 Term 更高的話則會降級;
  • Dry-Run 成功後,會增加自身的 Term 發起真正的選舉,如果收到多數派的選票則選 舉成功,把新的拓撲資訊通過心跳廣播到整個副本。

四、總結

  • 副本集是可用性、擴充性、維護性的有效保證,中等業務規模,生産環境建議優先選擇 部署該形态,如果是大型業務規模,建議使用 Sharing 形态;
  • 副本集使用務必使用高可用連接配接串的方式,避免業務通路單點;
  • 預設情況下的 Read/Write Concern 可以滿足絕大部分業務需求,特殊情況需要在一 緻性和性能之間做出取舍;
  • Oplog 是 MongoDB 的重要基礎設施,除了用于同步(全量 + 增量),還可用于構 建資料生态(ChangeStream);
  • MongoDB 以 Raft 協定為指導實作了自己的高可用機制,大部分情況下,主節點故障 15 秒内可選出新主。

快速掌握MongoDB核心技術目錄

電子書下載下傳:《玩轉MongoDB從入門到實戰》 https://developer.aliyun.com/article/780915
走進 MongoDB  https://developer.aliyun.com/article/781079
MongoDB聚合架構 https://developer.aliyun.com/article/781095
複制集使用及原理介紹  https://developer.aliyun.com/article/781137
分片叢集使用及原理介紹  https://developer.aliyun.com/article/781104
ChangeStreams 使用及原理 https://developer.aliyun.com/article/781107
事務功能使用及原理介紹 https://developer.aliyun.com/article/781111
MongoDB最佳實踐一 https://developer.aliyun.com/article/781139
MongoDB最佳實踐二  https://developer.aliyun.com/article/781141