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

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

那爲何要設置複製集(replica set)呢?mongodb

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

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記錄。ui

  • 將全部更改應用於數據集。 使用來自源的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,但在主數據庫不可用時容許從輔助服務器讀取過期的數據。 這爲故障轉移期間的應用程序提供了「只讀模式」。

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

相關文章
相關標籤/搜索