關注我,可以獲取最新知識、經(jīng)典面試題以及微服務技術分享
??MongoDB復制集(replica set):MongoDB復制集維護相同數(shù)據(jù)集的一組mongod進程,復制集是生產(chǎn)部署的基礎,具有數(shù)據(jù)冗余以及高可用性。
那為什么要設置復制集(replica set)呢?
- 由于復制集是通過在不同服務器上保存來副本,可保證數(shù)據(jù)在生產(chǎn)部署的冗余和可靠性,不會因為單點問題而丟失數(shù)據(jù)。
- 可以通過訪問不同服務器副本數(shù)據(jù)來提高數(shù)據(jù)讀取能力,從而提高整個系統(tǒng)的負載能力。
1. 復制集架構(gòu)原理
????副本集包含多個數(shù)據(jù)節(jié)點和可選的一個仲裁節(jié)點。 而在數(shù)據(jù)節(jié)點中:只有一個主節(jié)點(primary node),其他節(jié)點為為從節(jié)點(secondary nodes)。
??各個節(jié)點成員通過心跳機制進行通信,當主節(jié)點與從節(jié)點的通信的時間超過配置的electionTimeoutMillis期間(默認為10秒)時,符合條件的從節(jié)點要求選舉將自己指定為新主節(jié)點,群集嘗試完成新主節(jié)點的選舉并恢復正常操作。
主節(jié)點: 副本集只能有一個主節(jié)點能夠確認寫入操作來接收所有寫操作,并記錄其操作日志中的數(shù)據(jù)集的所有更改(記錄在oplog中)。
oplog: 它保存了修改存儲在數(shù)據(jù)庫中的數(shù)據(jù)的所有操作的滾動記錄,MongoDB在主節(jié)點服務器上應用數(shù)據(jù)庫操作,然后在主節(jié)點服務器的oplog上記錄操作,然后從節(jié)點成員在異步過程中通過心跳機制從任何其他成員導入oplog并應用這些操作,oplog中的每個操作都是冪等的。所有副本集成員都在local.oplog.rs集合中包含oplog的副本,這允許它們維護數(shù)據(jù)庫的當前狀態(tài)。
從節(jié)點: 復制主節(jié)點的oplog并將oplog記錄的操作應用于其數(shù)據(jù)集,如果主節(jié)點宕機了,將從符合條件的從節(jié)點選舉選出新的主節(jié)點,。 而且你可以通過配置實現(xiàn)特定的功能,比如:
- 防止從節(jié)點成為選舉中的主節(jié)點Primary,指定節(jié)點優(yōu)先級。
- 阻止應用程序從節(jié)點讀取數(shù)據(jù),從而允許應用程序運行需要與正常流量分離的應用程序,隱藏節(jié)點。
- 保留正在運行的“歷史”快照,以用于從某些錯誤中恢復,例如無意中刪除的數(shù)據(jù)庫,延遲節(jié)點
仲裁節(jié)點: 仲裁節(jié)點不維護數(shù)據(jù)集。 仲裁節(jié)點的目的是通過響應其他副本集節(jié)點的心跳和選舉請求來維護副本集中的仲裁。 因為它們不存儲數(shù)據(jù)集,所以仲裁節(jié)點可以是提供副本集仲裁功能的好方法,其資源成本比具有數(shù)據(jù)集的全功能副本集成員更便宜。 如果您的副本集具有偶數(shù)個成員,請?zhí)砑又俨霉?jié)點以獲得主要選舉中的大多數(shù)投票。而且仲裁節(jié)點總是只有1次選舉投票,因此允許副本集具有不均勻的投票成員數(shù),而沒有復制數(shù)據(jù)的額外成員的開銷。
心跳機制(Hearbeat): 復制集成員間默認每2s會發(fā)送一次心跳信息,如果10s未收到某個節(jié)點的心跳,則認為該節(jié)點已宕機不可以訪問;如果宕機的節(jié)點為Primary,Secondary(前提是可被選為Primary)會發(fā)起新的Primary選舉。仲裁員與其他集合成員之間的唯一溝通是:選舉期間的投票,心跳和配置數(shù)據(jù),而且這些交換未加密。
數(shù)據(jù)同步: 為了維護共享數(shù)據(jù)集的最新副本,副本的從節(jié)點設置同步或復制來自其他節(jié)點的數(shù)據(jù)。 MongoDB使用兩種形式的數(shù)據(jù)同步:初始化同步新節(jié)點同步完整的數(shù)據(jù)集,以及整個集群節(jié)點同步后續(xù)數(shù)據(jù)更改。
其中,初始化同步(Initial Sync)過程:
克隆除本地數(shù)據(jù)庫之外的所有數(shù)據(jù)庫。 要進行克隆,mongod會掃描每個源數(shù)據(jù)庫中的每個集合,并將所有數(shù)據(jù)插入到這些集合的自己的副本中。
初始同步會在為每個集合復制文檔時構(gòu)建所有集合索引。 在早期版本的MongoDB中,在此階段僅構(gòu)建_id索引。初始同步在數(shù)據(jù)復制期間提取新添加的oplog記錄。 確保目標成員在本地數(shù)據(jù)庫中有足夠的磁盤空間,以便在此數(shù)據(jù)復制階段的持續(xù)時間內(nèi)臨時存儲這些oplog記錄。
將所有更改應用于數(shù)據(jù)集。 使用來自源的oplog,mongod更新其數(shù)據(jù)集以反映副本集的當前狀態(tài)。
初始同步完成后,成員從STARTUP2轉(zhuǎn)換為SECONDARY。
2. 標準復制集架構(gòu)
??標準復制集架構(gòu)由三臺服務器,其中包括三個數(shù)據(jù)節(jié)點(一個主節(jié)點、兩個從節(jié)點)或兩個數(shù)據(jù)節(jié)點(一個主節(jié)點、一個從節(jié)點)和一個仲裁節(jié)點兩種情況。如下所示:
三個數(shù)據(jù)節(jié)點:
- 一個主節(jié)點;
- 兩個從節(jié)點,主節(jié)點宕機后,有機會選舉成為主節(jié)點。
當主庫宕機后,兩個從庫都會進行競選,其中一個變?yōu)橹鲙?,當原主庫恢復后,作為從庫加入當前的復制集群即可?/p>
兩個數(shù)據(jù)節(jié)點以及一個仲裁節(jié)點:
- 一個主節(jié)點;
- 一個從節(jié)點,有機會被選舉成為主節(jié)點;
- 一個仲裁節(jié)點,只有投票權利。
當主節(jié)點不可用時,將會選擇從節(jié)點成為主Primary,主節(jié)點恢復后,將其作為從節(jié)點加入到現(xiàn)有的復制集群中即可。
3. 節(jié)點類型
優(yōu)先級0型(Priority 0)節(jié)點
??優(yōu)先級0型節(jié)點不可以成為成為主節(jié)點,也不能觸發(fā)選舉。將從節(jié)點配置為優(yōu)先級為0以防止它成為主節(jié)點,這在多數(shù)據(jù)中心部署中特別有用,在許多情況下,您無需將備用數(shù)據(jù)庫設置為優(yōu)先級0.但是,在具有不同硬件或地理分布的副本集中,優(yōu)先級為0的備用數(shù)據(jù)庫可確保僅某些成員成為主數(shù)據(jù)庫,這樣可以根據(jù)實際網(wǎng)絡分區(qū)的網(wǎng)絡質(zhì)量等實際情況進行配置。
例如,一個數(shù)據(jù)中心承載主數(shù)據(jù)中心和輔助數(shù)據(jù)中心:
將第二個數(shù)據(jù)中心節(jié)點優(yōu)先級為0只能為從節(jié)點數(shù)據(jù)庫,而數(shù)據(jù)中心1中的節(jié)點才能成為主節(jié)點數(shù)據(jù)庫。(比如你跨機房A、B部署了一個復制集,并且想指定Primary必須在A機房,這時可以將B機房的復制集成員Priority設置為0,這樣Primary就一定會是A機房的成員),
隱藏型(Hidden)節(jié)點
隱藏型(Hidden)節(jié)點:
- 隱藏型從節(jié)點是維護主數(shù)據(jù)集的副本,但對客戶端應用程序不可見。隱藏型從節(jié)點適用于具有與副本集中其他成員不同的使用模式。
- 隱藏型從節(jié)點必須始終優(yōu)先為0型從節(jié)點,因此不能成為主節(jié)點。 隱藏型從節(jié)點可能會在選舉中投票。
- 隱藏型從節(jié)點將不會收到來自應用程序的請求。我們可以將隱藏型從節(jié)點專用于報表節(jié)點或是備份節(jié)點。
延遲型(Delayed)節(jié)點
??由于延遲型從節(jié)點是數(shù)據(jù)集的“滾動備份”或運行“歷史”快照,因此它們可以幫助您從各種人為錯誤中恢復。 例如,延遲節(jié)點可以從不成功的應用程序升級和操作員錯誤(包括丟棄的數(shù)據(jù)庫和集合)中恢復。而且延遲型從節(jié)點一定是優(yōu)先級為0的從節(jié)點,也是隱藏型從節(jié)點。不能成主節(jié)點,也不能給客戶端查詢。
在選擇延遲量時,請考慮延遲量:
- 必須等于或大于預期的維護窗口持續(xù)時間。
- 必須小于oplog的容量。
投票型(Vote)節(jié)點以及不可投票節(jié)點
??復制集節(jié)點可以通過配置members[n].votes來決定該節(jié)點是否具有投票權利!members[n].votes值為1具有投票權利為投票型節(jié)點,為0則不可以投票即為不可投票節(jié)點。無表決權的節(jié)點必須優(yōu)先級為0,也是優(yōu)先級大于0的成員不能為0值。雖然無表決權的成員不在選舉中投票,但這些成員持有副本集數(shù)據(jù)的副本,并且可以接受來自客戶端應用程序的讀取操作。
另外在副本集最多可包含50個成員,但只有7個投票成員,因此非投票成員允許副本集具有7個以上的成員。并投票成員只有具備以下狀態(tài)可以進行投票:
- 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. 部署結(jié)構(gòu):
最大投票成員為數(shù)量
??副本集最多可包含50個成員,但只有7個投票成員。 如果副本集已有7個投票成員,則其他成員必須是非投票成員。
部署奇數(shù)個成員
??副本集應該確保具有奇數(shù)個投票成員,如果您擁有偶數(shù)個投票成員,請部署仲裁節(jié)點,以便該集合具有奇數(shù)個投票成員。仲裁節(jié)點不存儲數(shù)據(jù)的副本并且需要更少的資源。 因此,您可以在應用程序服務器或其他共享進程上運行仲裁程序。
容錯能力
??副本集的容錯是當變?yōu)椴豢捎玫某蓡T數(shù),并且仍然在副本集中留下足夠的節(jié)點成員來選擇主節(jié)點成員。容錯是副本集大小的影響, 見下表:
Number of Members | Majority Required to Elect a New Primary | Fault Tolerance |
---|---|---|
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
因此可以得出,將成員添加為偶數(shù)個到副本集并不總是會增加容錯能力。但是,在這些情況下,其中將其中一個節(jié)點設置成隱藏型和延遲型從節(jié)點可以為專用功能提供支持,例如備份或報告。
提高讀負載能力
??在具有非常高讀取流量的部署中,您可以通過將讀取分發(fā)給從節(jié)點來提高讀取吞吐量。 隨著部署的增長,將節(jié)點添加或移動到備用數(shù)據(jù)中心以提高冗余和可用性。
副本集分布在兩個或更多數(shù)據(jù)中心
副本集分布在兩個或更多數(shù)據(jù)中心的優(yōu)勢:
- 如果其中一個數(shù)據(jù)中心發(fā)生故障,數(shù)據(jù)仍可用于讀取。
- 如果具有少數(shù)成員的數(shù)據(jù)中心發(fā)生故障,則副本集仍可以提供寫操作以及讀操作。但是,如果具有大多數(shù)成員的數(shù)據(jù)中心發(fā)生故障,則副本集將變?yōu)橹蛔x。
在不同地域部署數(shù)據(jù)節(jié)點(具有備用的數(shù)據(jù)中心)
??要在數(shù)據(jù)中心發(fā)生故障時保護您的數(shù)據(jù),請在備用數(shù)據(jù)中心至少保留一個成員。 如果可能,使用奇數(shù)個數(shù)據(jù)中心,并選擇一個成員分布,以最大限度地提高即使丟失數(shù)據(jù)中心的可能性,剩余的副本集成員可以形成可以形成“大多數(shù)”選取出主節(jié)點,并有提供數(shù)據(jù)的副本的能力。為確保主數(shù)據(jù)中心的節(jié)點在備用數(shù)據(jù)中心的成員之前被選為主要成員,請將備用數(shù)據(jù)中心中節(jié)點members[n].priority 設置為低于主數(shù)據(jù)中節(jié)點,如下所示:
根據(jù)部署結(jié)構(gòu)部署復制集示例
三個節(jié)點成員的副本集,成員合理分布以及解析如下:
- 兩個數(shù)據(jù)中心:數(shù)據(jù)中心1的兩個成員和數(shù)據(jù)中心2的一個成員。如果副本集的其中一個成員是仲裁者,則將仲裁者分配給具有數(shù)據(jù)承載成員的數(shù)據(jù)中心1。
- 如果數(shù)據(jù)中心1關閉,則副本集將變?yōu)橹蛔x。
- 如果數(shù)據(jù)中心2關閉,則副本集仍然可寫,因為數(shù)據(jù)中心1中的成員可以進行選舉。
- 三個數(shù)據(jù)中心:一個成員到數(shù)據(jù)中心1,一個成員到數(shù)據(jù)中心2,一個成員到數(shù)據(jù)中心3。
- 如果任何數(shù)據(jù)中心發(fā)生故障,副本集仍然可寫,因為其余成員可以舉行選舉。
五副節(jié)點成員的副本集,成員合理分布以及解析如下:
- 兩個數(shù)據(jù)中心:數(shù)據(jù)中心1的三個成員和數(shù)據(jù)中心2的兩個成員。
- 如果數(shù)據(jù)中心1關閉,則副本集將變?yōu)橹蛔x。
- 如果數(shù)據(jù)中心2關閉,則副本集仍然可寫,因為數(shù)據(jù)中心1中的成員可以創(chuàng)建多數(shù)。
- 三個數(shù)據(jù)中心:數(shù)據(jù)中心1的兩個成員,數(shù)據(jù)中心2的兩個成員和數(shù)據(jù)中心3的一個成員。
- 如果任何數(shù)據(jù)中心發(fā)生故障,副本集仍然可寫,因為其余成員可以舉行選舉。
高可用
集群具有自主選舉能力,影響選取的因子和條件有以下:
- 選取協(xié)議
- 心跳機制:復制集成員間默認每2s會發(fā)送一次心跳信息,如果10s未收到某個節(jié)點的心跳,則認為該節(jié)點已宕機不可以訪問;如果宕機的節(jié)點為Primary,Secondary(前提是可被選為Primary)會發(fā)起新的Primary選舉。
- 節(jié)點優(yōu)先權:每個節(jié)點都會傾向于投票給優(yōu)先級最高的節(jié)點,優(yōu)先級為0的節(jié)點不能成為主節(jié)點Primary,也不會主動發(fā)起Primary選舉。當Primary發(fā)現(xiàn)有優(yōu)先級更高Secondary,并且該Secondary的數(shù)據(jù)落后在10s內(nèi),則Primary會主動降級,讓優(yōu)先級更高的Secondary有成為Primary的機會。
- 丟失數(shù)據(jù)中心:使用分布式副本集,數(shù)據(jù)中心的丟失可能會影響其他數(shù)據(jù)中心或數(shù)據(jù)中心中其余成員選擇主數(shù)據(jù)庫的能力。如果可能,在數(shù)據(jù)中心之間分發(fā)副本集成員,以最大限度地提高即使丟失數(shù)據(jù)中心的可能性,其余一個副本集成員也可以成為新的主要成員。
- 網(wǎng)絡分區(qū):只有跟大多數(shù)投票節(jié)點間能保持網(wǎng)絡暢通,才有機會被選主節(jié)點Primary;如果Primary與大多數(shù)的節(jié)點失去聯(lián)系,Primary會主動降級為Secondary。當發(fā)生網(wǎng)絡分區(qū)時,可能在短時間內(nèi)出現(xiàn)多個Primary,故Driver在寫入時,最好設置『大多數(shù)成功』的策略,這樣即使出現(xiàn)多個Primary,也只有一個Primary能成功寫入大多數(shù)。
5. Write concern和Read Preference
5.1 Write concern
??Write concern描述了在操作返回成功之前必須確認寫操作的數(shù)據(jù)承載成員(即主節(jié)點成員和從節(jié)點成員,但不是仲裁者)的數(shù)量。成員只能在收到并成功應用寫入后才能確認寫入操作。
對于副本集,默認的w:1的Write concern 要求在返回Write concern確認之前,只有Primary主節(jié)點確認寫入。您可以指定一個大于1的整數(shù)值,以要求來自主節(jié)點的確認以及滿足指定值所需的多個從節(jié)點,最多為副本集中數(shù)據(jù)承載成員的總數(shù)。
??Client 發(fā)出帶有需要寫入請求的寫入操作Write concern將等待直到主節(jié)點接收來自指定需要寫入詢問所有數(shù)量的成員的確認。對于大于1或w:“majority ”的寫入咨詢 Write concern,主節(jié)點接收到所需的從節(jié)點數(shù)量在返回確認可寫入答復通知client確認寫入。對于w:1的寫入咨詢Write Concern,主要可以在本地應用(單機模式)寫入時立即返回可寫入答復,因為它有資格對所請求的Write Concern做出判決。
??指定超時等待寫入咨詢Write concern的寫操作僅表示所需數(shù)量的副本集成員未在wtimeout時間段內(nèi)確認寫操作。它不一定表示主節(jié)點Primary未能應用寫入。
檢驗寫操作
在insert()方法中增加write Concern選項,并指定“大多數(shù)”寫入關注和5秒超時,以便操作不會無限期地阻塞,如下:
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)
??例如,在3個節(jié)點成員的副本集中,操作將需要來自3個成員中的2個的確認。如果稍后縮放副本集以包括兩個額外的投票節(jié)點,則相同的操作將需要來自5個副本集成員中的3個的確認。如果主節(jié)點服務器未在wtimeout限制內(nèi)返回寫入咨詢 Write concern確認,則寫入操作將失敗并出現(xiàn)寫入問題錯誤。
修改默認Write Concern
??可以通過在副本集配置中設置settings.getLastErrorDefaults設置來修改副本集的默認寫入問題。配置在返回之前等待寫操作(在大多數(shù)投票成員上確認后)操作命令:
cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
5.2 Read Preference
??Read Preference是mongodb如何將讀操作分配到節(jié)點中,默認情況下,應用程序?qū)⑵渥x取操作定向到副本集中的主要成員(即讀取首選項模式“primary”)。 但是,客戶端可以指定讀取首選項以將讀取操作發(fā)送到輔助節(jié)點。Read Preference 模式如下:
- primary: 默認規(guī)則,所有讀請求發(fā)到Primary
- primaryPreferred: Primary優(yōu)先,如果Primary不可達,請求Secondary
- secondary: 所有的讀請求都發(fā)到secondary
- secondaryPreferred:Secondary優(yōu)先,當所有Secondary不可達時,請求Primary
- nearest:讀請求發(fā)送到最近的可達節(jié)點上(通過ping探測得出最近的節(jié)點)
以下是使用讀取首選項模式的常見用例:
- 為地理分布的應用程序提供本地讀取。
- 如果您在多個數(shù)據(jù)中心中安裝了應用程序服務器,則可以考慮使用地理位置分散的副本集并使用非主要或最近的讀取首選項。 這允許客戶端從最低延遲成員讀取,而不是始終從主要成員讀取。
- 在故障轉(zhuǎn)移期間維護可用性。
- 如果希望應用程序在正常情況下從主數(shù)據(jù)庫讀取,則允許使用primaryPreferred,但在主數(shù)據(jù)庫不可用時允許從輔助服務器讀取過時的數(shù)據(jù)。 這為故障轉(zhuǎn)移期間的應用程序提供了“只讀模式”。