MongoDB系列-解決面試中可能遇到的MongoDB複製集(replica set)問題

關注我,可以獲取最新知識、經典面試題以及微服務技術分享

  MongoDB複製集(replica set):MongoDB複製集維護相同數據集的一組mongod進程,複製集是生產部署的基礎,具有數據冗餘以及高可用性。

那爲什麼要設置複製集(replica set)呢?

  • 由於複製集是通過在不同服務器上保存來副本,可保證數據在生產部署的冗餘和可靠性,不會因爲單點問題而丟失數據。
  • 可以通過訪問不同服務器副本數據來提高數據讀取能力,從而提高整個系統的負載能力。

1. 複製集架構原理

    副本集包含多個數據節點可選的一個仲裁節點。 而在數據節點中:只有一個主節點(primary node),其他節點爲爲從節點(secondary nodes)
  各個節點成員通過心跳機制進行通信,當主節點與從節點的通信的時間超過配置的electionTimeoutMillis期間(默認爲10秒)時,符合條件的從節點要求選舉將自己指定爲新主節點,羣集嘗試完成新主節點的選舉並恢復正常操作。


主節點: 副本集只能有一個主節點能夠確認寫入操作來接收所有寫操作,並記錄其操作日誌中的數據集的所有更改(記錄在oplog中)。

oplog: 它保存了修改存儲在數據庫中的數據的所有操作的滾動記錄,MongoDB在主節點服務器上應用數據庫操作,然後在主節點服務器的oplog上記錄操作,然後從節點成員在異步過程中通過心跳機制從任何其他成員導入oplog並應用這些操作,oplog中的每個操作都是冪等的。所有副本集成員都在local.oplog.rs集合中包含oplog的副本,這允許它們維護數據庫的當前狀態。

從節點: 複製主節點的oplog並將oplog記錄的操作應用於其數據集,如果主節點宕機了,將從符合條件的從節點選舉選出新的主節點,。 而且你可以通過配置實現特定的功能,比如:

  • 防止從節點成爲選舉中的主節點Primary,指定節點優先級。
  • 阻止應用程序從節點讀取數據,從而允許應用程序運行需要與正常流量分離的應用程序,隱藏節點。
  • 保留正在運行的“歷史”快照,以用於從某些錯誤中恢復,例如無意中刪除的數據庫,延遲節點

仲裁節點: 仲裁節點不維護數據集。 仲裁節點的目的是通過響應其他副本集節點的心跳和選舉請求來維護副本集中的仲裁。 因爲它們不存儲數據集,所以仲裁節點可以是提供副本集仲裁功能的好方法,其資源成本比具有數據集的全功能副本集成員更便宜。 如果您的副本集具有偶數個成員,請添加仲裁節點以獲得主要選舉中的大多數投票。而且仲裁節點總是隻有1次選舉投票,因此允許副本集具有不均勻的投票成員數,而沒有複製數據的額外成員的開銷。


心跳機制(Hearbeat): 複製集成員間默認每2s會發送一次心跳信息,如果10s未收到某個節點的心跳,則認爲該節點已宕機不可以訪問;如果宕機的節點爲Primary,Secondary(前提是可被選爲Primary)會發起新的Primary選舉。仲裁員與其他集合成員之間的唯一溝通是:選舉期間的投票,心跳和配置數據,而且這些交換未加密。

數據同步: 爲了維護共享數據集的最新副本,副本的從節點設置同步或複製來自其他節點的數據。 MongoDB使用兩種形式的數據同步:初始化同步新節點同步完整的數據集,以及整個集羣節點同步後續數據更改。

其中,初始化同步(Initial Sync)過程:

  • 克隆除本地數據庫之外的所有數據庫。 要進行克隆,mongod會掃描每個源數據庫中的每個集合,並將所有數據插入到這些集合的自己的副本中。

初始同步會在爲每個集合複製文檔時構建所有集合索引。 在早期版本的MongoDB中,在此階段僅構建_id索引。

  • 初始同步在數據複製期間提取新添加的oplog記錄。 確保目標成員在本地數據庫中有足夠的磁盤空間,以便在此數據複製階段的持續時間內臨時存儲這些oplog記錄。
  • 將所有更改應用於數據集。 使用來自源的oplog,mongod更新其數據集以反映副本集的當前狀態。

初始同步完成後,成員從STARTUP2轉換爲SECONDARY。

2. 標準複製集架構

  標準複製集架構由三臺服務器,其中包括三個數據節點(一個主節點、兩個從節點)或兩個數據節點(一個主節點、一個從節點)和一個仲裁節點兩種情況。如下所示:

三個數據節點:

  • 一個主節點;
  • 兩個從節點,主節點宕機後,有機會選舉成爲主節點。


當主庫宕機後,兩個從庫都會進行競選,其中一個變爲主庫,當原主庫恢復後,作爲從庫加入當前的複製集羣即可。

兩個數據節點以及一個仲裁節點:

  • 一個主節點;
  • 一個從節點,有機會被選舉成爲主節點;
  • 一個仲裁節點,只有投票權利。


當主節點不可用時,將會選擇從節點成爲主Primary,主節點恢復後,將其作爲從節點加入到現有的複製集羣中即可。

3. 節點類型

優先級0型(Priority 0)節點

  優先級0型節點不可以成爲成爲主節點,也不能觸發選舉。將從節點配置爲優先級爲0以防止它成爲主節點,這在多數據中心部署中特別有用,在許多情況下,您無需將備用數據庫設置爲優先級0.但是,在具有不同硬件或地理分佈的副本集中,優先級爲0的備用數據庫可確保僅某些成員成爲主數據庫,這樣可以根據實際網絡分區的網絡質量等實際情況進行配置。

例如,一個數據中心承載主數據中心和輔助數據中心:


將第二個數據中心節點優先級爲0只能爲從節點數據庫,而數據中心1中的節點才能成爲主節點數據庫。(比如你跨機房A、B部署了一個複製集,並且想指定Primary必須在A機房,這時可以將B機房的複製集成員Priority設置爲0,這樣Primary就一定會是A機房的成員),

隱藏型(Hidden)節點

隱藏型(Hidden)節點:

  • 隱藏型從節點是維護主數據集的副本,但對客戶端應用程序不可見。隱藏型從節點適用於具有與副本集中其他成員不同的使用模式。
  • 隱藏型從節點必須始終優先爲0型從節點,因此不能成爲主節點。 隱藏型從節點可能會在選舉中投票。
  • 隱藏型從節點將不會收到來自應用程序的請求。我們可以將隱藏型從節點專用於報表節點或是備份節點。

延遲型(Delayed)節點

  由於延遲型從節點是數據集的“滾動備份”或運行“歷史”快照,因此它們可以幫助您從各種人爲錯誤中恢復。 例如,延遲節點可以從不成功的應用程序升級和操作員錯誤(包括丟棄的數據庫和集合)中恢復。而且延遲型從節點一定是優先級爲0的從節點,也是隱藏型從節點。不能成主節點,也不能給客戶端查詢。

在選擇延遲量時,請考慮延遲量:

  • 必須等於或大於預期的維護窗口持續時間。
  • 必須小於oplog的容量。

投票型(Vote)節點以及不可投票節點

  複製集節點可以通過配置members[n].votes來決定該節點是否具有投票權利!members[n].votes值爲1具有投票權利爲投票型節點,爲0則不可以投票即爲不可投票節點。無表決權的節點必須優先級爲0,也是優先級大於0的成員不能爲0值。雖然無表決權的成員不在選舉中投票,但這些成員持有副本集數據的副本,並且可以接受來自客戶端應用程序的讀取操作。

另外在副本集最多可包含50個成員,但只有7個投票成員,因此非投票成員允許副本集具有7個以上的成員。並投票成員只有具備以下狀態可以進行投票:

  • PRIMARY
  • SECONDARY
  • STARTUP2
  • RECOVERING
  • ARBITER
  • ROLLBACK


配置:

{
   "_id" : <num>,
   "host" : <hostname:port>,
   "arbiterOnly" : false,
   "buildIndexes" : true,
   "hidden" : false,
   "priority" : 0,
   "tags" : {
},
   "slaveDelay" : NumberLong(0),
   "votes" : 0
}




4. 部署結構:

最大投票成員爲數量
  副本集最多可包含50個成員,但只有7個投票成員。 如果副本集已有7個投票成員,則其他成員必須是非投票成員。

部署奇數個成員
  副本集應該確保具有奇數個投票成員,如果您擁有偶數個投票成員,請部署仲裁節點,以便該集合具有奇數個投票成員。仲裁節點不存儲數據的副本並且需要更少的資源。 因此,您可以在應用程序服務器或其他共享進程上運行仲裁程序。
容錯能力
  副本集的容錯是當變爲不可用的成員數,並且仍然在副本集中留下足夠的節點成員來選擇主節點成員。容錯是副本集大小的影響, 見下表:

Number of Members Majority Required to Elect a New Primary Fault Tolerance
3 2 1
4 3 1
5 3 2
6 4 2

因此可以得出,將成員添加爲偶數個到副本集並不總是會增加容錯能力。但是,在這些情況下,其中將其中一個節點設置成隱藏型和延遲型從節點可以爲專用功能提供支持,例如備份或報告。

提高讀負載能力
  在具有非常高讀取流量的部署中,您可以通過將讀取分發給從節點來提高讀取吞吐量。 隨着部署的增長,將節點添加或移動到備用數據中心以提高冗餘和可用性。

副本集分佈在兩個或更多數據中心
副本集分佈在兩個或更多數據中心的優勢:

  • 如果其中一個數據中心發生故障,數據仍可用於讀取。
  • 如果具有少數成員的數據中心發生故障,則副本集仍可以提供寫操作以及讀操作。但是,如果具有大多數成員的數據中心發生故障,則副本集將變爲只讀。

在不同地域部署數據節點(具有備用的數據中心)
  要在數據中心發生故障時保護您的數據,請在備用數據中心至少保留一個成員。 如果可能,使用奇數個數據中心,並選擇一個成員分佈,以最大限度地提高即使丟失數據中心的可能性,剩餘的副本集成員可以形成可以形成“大多數”選取出主節點,並有提供數據的副本的能力。爲確保主數據中心的節點在備用數據中心的成員之前被選爲主要成員,請將備用數據中心中節點members[n].priority 設置爲低於主數據中節點,如下所示:

根據部署結構部署複製集示例
三個節點成員的副本集,成員合理分佈以及解析如下

  • 兩個數據中心:數據中心1的兩個成員和數據中心2的一個成員。如果副本集的其中一個成員是仲裁者,則將仲裁者分配給具有數據承載成員的數據中心1。
  • 如果數據中心1關閉,則副本集將變爲只讀。
  • 如果數據中心2關閉,則副本集仍然可寫,因爲數據中心1中的成員可以進行選舉。
  • 三個數據中心:一個成員到數據中心1,一個成員到數據中心2,一個成員到數據中心3。
  • 如果任何數據中心發生故障,副本集仍然可寫,因爲其餘成員可以舉行選舉。

五副節點成員的副本集,成員合理分佈以及解析如下:

  • 兩個數據中心:數據中心1的三個成員和數據中心2的兩個成員。
  • 如果數據中心1關閉,則副本集將變爲只讀。
  • 如果數據中心2關閉,則副本集仍然可寫,因爲數據中心1中的成員可以創建多數。
  • 三個數據中心:數據中心1的兩個成員,數據中心2的兩個成員和數據中心3的一個成員。
  • 如果任何數據中心發生故障,副本集仍然可寫,因爲其餘成員可以舉行選舉。

高可用
集羣具有自主選舉能力,影響選取的因子和條件有以下:

  • 選取協議
  • 心跳機制:複製集成員間默認每2s會發送一次心跳信息,如果10s未收到某個節點的心跳,則認爲該節點已宕機不可以訪問;如果宕機的節點爲Primary,Secondary(前提是可被選爲Primary)會發起新的Primary選舉。
  • 節點優先權:每個節點都會傾向於投票給優先級最高的節點,優先級爲0的節點不能成爲主節點Primary,也不會主動發起Primary選舉。當Primary發現有優先級更高Secondary,並且該Secondary的數據落後在10s內,則Primary會主動降級,讓優先級更高的Secondary有成爲Primary的機會。
  • 丟失數據中心:使用分佈式副本集,數據中心的丟失可能會影響其他數據中心或數據中心中其餘成員選擇主數據庫的能力。如果可能,在數據中心之間分發副本集成員,以最大限度地提高即使丟失數據中心的可能性,其餘一個副本集成員也可以成爲新的主要成員。
  • 網絡分區:只有跟大多數投票節點間能保持網絡暢通,纔有機會被選主節點Primary;如果Primary與大多數的節點失去聯繫,Primary會主動降級爲Secondary。當發生網絡分區時,可能在短時間內出現多個Primary,故Driver在寫入時,最好設置『大多數成功』的策略,這樣即使出現多個Primary,也只有一個Primary能成功寫入大多數。

5. Write concern和Read Preference

5.1 Write concern

  Write concern描述了在操作返回成功之前必須確認寫操作的數據承載成員(即主節點成員和從節點成員,但不是仲裁者)的數量。成員只能在收到併成功應用寫入後才能確認寫入操作。
對於副本集,默認的w:1的Write concern 要求在返回Write concern確認之前,只有Primary主節點確認寫入。您可以指定一個大於1的整數值,以要求來自主節點的確認以及滿足指定值所需的多個從節點,最多爲副本集中數據承載成員的總數。

  Client 發出帶有需要寫入請求的寫入操作Write concern將等待直到主節點接收來自指定需要寫入詢問所有數量的成員的確認。對於大於1或w:“majority ”的寫入諮詢 Write concern,主節點接收到所需的從節點數量在返回確認可寫入答覆通知client確認寫入。對於w:1的寫入諮詢Write Concern,主要可以在本地應用(單機模式)寫入時立即返回可寫入答覆,因爲它有資格對所請求的Write Concern做出判決。

  指定超時等待寫入諮詢Write concern的寫操作僅表示所需數量的副本集成員未在wtimeout時間段內確認寫操作。它不一定表示主節點Primary未能應用寫入。

檢驗寫操作
在insert()方法中增加write Concern選項,並指定“大多數”寫入關注和5秒超時,以便操作不會無限期地阻塞,如下:

db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)

  例如,在3個節點成員的副本集中,操作將需要來自3個成員中的2個的確認。如果稍後縮放副本集以包括兩個額外的投票節點,則相同的操作將需要來自5個副本集成員中的3個的確認。如果主節點服務器未在wtimeout限制內返回寫入諮詢 Write concern確認,則寫入操作將失敗並出現寫入問題錯誤。

修改默認Write Concern
  可以通過在副本集配置中設置settings.getLastErrorDefaults設置來修改副本集的默認寫入問題。配置在返回之前等待寫操作(在大多數投票成員上確認後)操作命令:

cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)

5.2 Read Preference

  Read Preference是mongodb如何將讀操作分配到節點中,默認情況下,應用程序將其讀取操作定向到副本集中的主要成員(即讀取首選項模式“primary”)。 但是,客戶端可以指定讀取首選項以將讀取操作發送到輔助節點。Read Preference 模式如下:

  • primary: 默認規則,所有讀請求發到Primary
  • primaryPreferred: Primary優先,如果Primary不可達,請求Secondary
  • secondary: 所有的讀請求都發到secondary
  • secondaryPreferred:Secondary優先,當所有Secondary不可達時,請求Primary
  • nearest:讀請求發送到最近的可達節點上(通過ping探測得出最近的節點)

以下是使用讀取首選項模式的常見用例:

  • 爲地理分佈的應用程序提供本地讀取。
  • 如果您在多個數據中心中安裝了應用程序服務器,則可以考慮使用地理位置分散的副本集並使用非主要或最近的讀取首選項。 這允許客戶端從最低延遲成員讀取,而不是始終從主要成員讀取。
  • 在故障轉移期間維護可用性。
  • 如果希望應用程序在正常情況下從主數據庫讀取,則允許使用primaryPreferred,但在主數據庫不可用時允許從輔助服務器讀取過時的數據。 這爲故障轉移期間的應用程序提供了“只讀模式”。

最後可關注公衆號,一起學習,每天會分享乾貨,還有學習視頻領取!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章