MongoDB做爲現在主流的文檔型數據庫,在大小公司都有普遍的應用。相信對服務有可用性要求的公司,都或多或少會用到複製集功能。複製集正是MongoDB提供的一整套高可用性的解決方案。現階段不少文章都是講述如何建立一個副本集,可是對副本集的原理不多提示。因此,第一篇文章將詳盡的闡述其中各個概念,以便你對複製集功能有個總體的瞭解。web
如今假設你運行一個web服務,服務後面連着一個MongoDB實例。若是這個時候實例掛掉了,整個web服務都將不可用,這在生產環境必定是不容許的。那麼若是咱們運行多個MongoDB的實例,掛掉一個由另一個頂上,整個服務的可用性都將大幅提升。這樣的多個實例的集合就稱爲複製集。固然複製集上的實例,都保存着相同的數據。redis
MongoDB實現的複製集是主從架構,以下圖所示 算法
在複製集中存在兩種不一樣類型的節點分別是Primary
(後文用主節點指代)以及Secondary
(後文用從節點指代)。數據庫
在一個複製集中只能存在一個主節點,但能夠存在多個從節點。從節點不可接受寫入操做,主節點接受寫入操做,經過oplog
的形式,將數據同步給從節點。 oplog
是數據的寫入的日誌。你插入一條記錄,那麼日誌就會增長一行插入操做。從節點拿到日誌,在本身服務上面重放這個操做,就實現了數據的同步。bash
當咱們的主節點由於意外狀況掛掉,其餘從節點會選舉出一個節點做爲新的主節點。 架構
選舉算法採用了著名的分佈式算法Raft
(
zh.wikipedia.org/wiki/Raft)。
通常來講選舉會發生在如下幾種狀況裏面:分佈式
當咱們只有一臺MongoDB實例的時候,客戶端的一個插入記錄,寫入成功直接返回success。可是,如今咱們有一個複製集,那麼客戶端的寫入操做怎麼纔算成功寫入呢?ui
這就要提到MongoDB的寫入配置Write Concern
。Write Concern
是這樣一種k,v結構{ w: <value>, j: <boolean>, wtimeout: <number> }
。spa
w表示須要多少個節點確認纔算寫入成功,默認值爲1({'w': 1}
)。表示寫入Primary
節點後就算寫入成功。若是填n
表示須要寫入n個節點,纔可以算寫入成功。日誌
w還有另外一種選項majority
,表示寫入大部分節點算成功寫入。舉個例子,如今有3個節點參與選舉投票,那麼成功寫入2個就算寫入成功。
j表示是否須要成功寫入journal files
。
表示超時時間,這裏須要額外注意,在有的臨界點寫入成功也有可能返回超時。可是MongoDB是不會去回滾寫入成功的數據的。
Write Concern
能夠直接修改集羣配置
cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
複製代碼
也能夠增長
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)
複製代碼
第二個參數作單獨的配置。
MongoDB的從節點能夠大體分爲五類:
這類從節點屬於priority
爲1,能夠正常的選舉,複製數據。
這類節點只能複製數據,不能被選舉爲主節點,也不能觸發選舉的開始。這類節點一般做爲跟隨節點。所謂跟隨節點,只存儲數據,當普通節點宕機時,能夠迅速替換到主節點。
隱藏節點對於客戶端是不可見的,隱藏節點的priority必定要爲0.
延遲節點不會當即同步主節點的數據,會有個時間上的延遲。比方說7點主節點寫入一條數據,8點延遲節點纔會同步這點數據。延遲節點最好設置爲隱藏節點,以避免客戶端讀取到髒數據。延遲節點的做用,主要是做爲備份和回滾使用。
這類節點不含數據,僅僅是做爲投票使用。有的時候咱們可能有4個節點用來投票,可是投票節點數須要奇數個,就能夠部署一臺仲裁者,使投票節點數爲奇數。
和redis
類似,數據同步遵循兩種形式,當新節點加入集羣時,爲把數據全量傳輸過去。第一次同步事後,會根據oplog
進行操做重放,增量更新。