布偶貓網(wǎng)頁設(shè)計(jì)教程百度seo入駐
一、前言
MongoDB 有三種集群架構(gòu)模式,分別為主從復(fù)制(Master-Slaver)、副本集(Replica Set)和分片(Sharding)模式。
- Master-Slaver 是一種主從復(fù)制的模式,目前已經(jīng)不推薦使用。
- Replica Set 模式取代了 Master-Slaver 模式,是一種互為主從的關(guān)系。Replica Set 將數(shù)據(jù)復(fù)制多份保存,不同服務(wù)器保存同一份數(shù)據(jù),在出現(xiàn)故障時(shí)自動(dòng)切換,實(shí)現(xiàn)故障轉(zhuǎn)移,在實(shí)際生產(chǎn)中非常實(shí)用。
- Sharding 模式適合處理大量數(shù)據(jù),它將數(shù)據(jù)分開存儲(chǔ),不同服務(wù)器保存不同的數(shù)據(jù),所有服務(wù)器數(shù)據(jù)的總和即為整個(gè)數(shù)據(jù)集。
二、主從復(fù)制模式
MongoDB 提供的第一種冗余策略就是 Master-Slave 策略,這個(gè)也是分布式系統(tǒng)最開始的冗余策略,這種是一種熱備策略。
Master-Slave 架構(gòu)一般用于備份或者做讀寫分離,一般是一主一從設(shè)計(jì)和一主多從設(shè)計(jì)。
Master-Slave 由主從角色構(gòu)成:
Master ( 主 )
可讀可寫,當(dāng)數(shù)據(jù)有修改的時(shí)候,會(huì)將 Oplog 同步到所有連接的 Salve 上去。
Slave ( 從 )
只讀,所有的 Slave 從 Master 同步數(shù)據(jù),從節(jié)點(diǎn)與從節(jié)點(diǎn)之間不感知。
如圖:
2.1 主從復(fù)制對(duì)讀寫分離的思考
主從復(fù)制老生常談的問題:數(shù)據(jù)不一致的問題。
根本原因在于只有 Master 節(jié)點(diǎn)可以寫,Slave 節(jié)點(diǎn)只能同步 Master 數(shù)據(jù)并對(duì)外提供讀服務(wù),當(dāng)你查詢 Slave 節(jié)點(diǎn)的數(shù)據(jù)時(shí),由于網(wǎng)絡(luò)延遲等其它因素導(dǎo)致 Slave 節(jié)點(diǎn)還沒有完全同步 Master 節(jié)點(diǎn)的數(shù)據(jù),這就會(huì)導(dǎo)致主從不一致,跟 MySQL 的主從復(fù)制如出一轍,只不過 MySQL 時(shí) binlog 同步,而 MongoDB 是 oplog 同步。
所以,總結(jié)來說:讀寫分離的架構(gòu)只適合特定場景,對(duì)于必須需要數(shù)據(jù)強(qiáng)一致的場景是不合適這種讀寫分離的。
2.2 主從復(fù)制對(duì)容災(zāi)的思考
當(dāng) Master 節(jié)點(diǎn)出現(xiàn)故障的時(shí)候,由于 Slave 節(jié)點(diǎn)有備份數(shù)據(jù),可以通過人為 Check 和操作,手動(dòng)把 Slave 節(jié)點(diǎn)指定為 Master 節(jié)點(diǎn),這樣又能對(duì)外提供服務(wù)了。
- Master-Slave 只區(qū)分兩種角色:Master 節(jié)點(diǎn),Slave 節(jié)點(diǎn);
- Master-Slave 的角色是靜態(tài)配置的,不能自動(dòng)切換角色,必須人為指定;
- 用戶只能寫 Master 節(jié)點(diǎn),Slave 節(jié)點(diǎn)只能從 Master 拉數(shù)據(jù);
- 還有一個(gè)關(guān)鍵點(diǎn):Slave 節(jié)點(diǎn)只和 Master 通信,Slave 之間相互不感知,這種好處對(duì)于 Master 來說優(yōu)點(diǎn)是非常輕量,缺點(diǎn)是:系統(tǒng)明顯存在單點(diǎn),那么多 Slave 只能從 Master 拉數(shù)據(jù),而無法提供自己的判斷;
MongoDB 3.6 起已不推薦使用主從模式,自 MongoDB 3.2 起,分片群集組件已棄用主從復(fù)制。因?yàn)?Master-Slave 其中 Master 宕機(jī)后不能自動(dòng)恢復(fù),只能靠人為操作,可靠性也差,操作不當(dāng)就存在丟數(shù)據(jù)的風(fēng)險(xiǎn)。
三、副本集模式
3.1 副本集模式角色
副本集(Replica Set)是 mongod 的實(shí)例集合,包含三類節(jié)點(diǎn)角色:
Primary( 主節(jié)點(diǎn) )
只有 Primary 是可讀可寫的,Primary 接收所有的寫請(qǐng)求,然后把數(shù)據(jù)同步到所有 Secondary 。一個(gè) Replica Set 只有一個(gè) Primary 節(jié)點(diǎn),當(dāng) Primary 掛掉后,其他 Secondary 或者 Arbiter 節(jié)點(diǎn)會(huì)重新選舉出來一個(gè) Primary 節(jié)點(diǎn),這樣就又可以提供服務(wù)了。
讀請(qǐng)求默認(rèn)是發(fā)到 Primary 節(jié)點(diǎn)處理,如果需要故意轉(zhuǎn)發(fā)到 Secondary 需要客戶端修改一下配置(注意:是客戶端配置,決策權(quán)在客戶端)。
那有人又會(huì)想了,這里也存在 Primary 和 Secondary 節(jié)點(diǎn)角色的分類,豈不是也存在單點(diǎn)問題?
這里和 Master-Slave 模式的最大區(qū)別在于,Primary 角色是通過整個(gè)集群共同選舉出來的,人人都可能成為 Primary ,人人最開始只是 Secondary ,而這個(gè)選舉過程完全自動(dòng),不需要人為參與。
Secondary( 副本節(jié)點(diǎn) )
數(shù)據(jù)副本節(jié)點(diǎn),當(dāng)主節(jié)點(diǎn)掛掉的時(shí)候,參與選主。
思考一個(gè)問題:Secondary 和 Master-Slave 模式的 Slave 角色有什么區(qū)別?
最根本的一個(gè)不同在于:Secondary 相互有心跳,Secondary 可以作為數(shù)據(jù)源,Replica 可以是一種鏈?zhǔn)降膹?fù)制模式。
Arbiter( 仲裁者 )
不存數(shù)據(jù),不會(huì)被選為主,只進(jìn)行選主投票。使用 Arbiter 可以減輕在減少數(shù)據(jù)的冗余備份,又能提供高可用的能力。
如下圖:
3.2 為什么要使用副本集?
3.2.1 高可用
- 防止設(shè)備(服務(wù)器、網(wǎng)絡(luò))故障
- 提供自動(dòng) failover 功能
- 技術(shù)來保證高可用
3.2.2 災(zāi)難恢復(fù)
- 當(dāng)發(fā)生故障時(shí),可以從其他節(jié)點(diǎn)恢復(fù),用于備份。
3.2.3 功能隔離
- 我們可以在備節(jié)點(diǎn)上執(zhí)行讀操作,減少主節(jié)點(diǎn)的壓力
- 比如:用于分析、報(bào)表,數(shù)據(jù)挖掘,系統(tǒng)任務(wù)等。
3.3 副本集集群架構(gòu)原理
一個(gè)副本集中Primary
節(jié)點(diǎn)上能夠完成讀寫操作,Secondary
節(jié)點(diǎn)僅能用于讀操作。Primary
節(jié)點(diǎn)需要記錄所有改變數(shù)據(jù)庫狀態(tài)的操作,這些記錄保存在?oplog
?中,這個(gè)文件存儲(chǔ)在?local
?數(shù)據(jù)庫,各個(gè)Secondary
?節(jié)點(diǎn)通過此?oplog
?來復(fù)制數(shù)據(jù)并應(yīng)用于本地,保持本地的數(shù)據(jù)與主節(jié)點(diǎn)的一致。oplog
?具有冪等性,即無論執(zhí)行幾次其結(jié)果一致,這個(gè)比?mysql
?的二進(jìn)制日志更好用。
oplog
的組成結(jié)構(gòu)
{"ts" : Timestamp(1446011584, 2),"h" : NumberLong("1687359108795812092"),"v" : 2,"op" : "i","ns" : "test.nosql","o" : { "_id" : ObjectId("563062c0b085733f34ab4129"), "name" : "mongodb", "score" : "10"}
}ts:操作時(shí)間,當(dāng)前timestamp + 計(jì)數(shù)器,計(jì)數(shù)器每秒都被重置
h:操作的全局唯一標(biāo)識(shí)
v:oplog版本信息
op:操作類型i:插入操作u:更新操作d:刪除操作 c:執(zhí)行命令(如createDatabase,dropDatabase)
n:空操作,特殊用途
ns:操作針對(duì)的集合
o:操作內(nèi)容
o2:更新查詢條件,僅update操作包含該字段
副本集數(shù)據(jù)同步分為初始化同步
和keep復(fù)制同步
。初始化同步指全量從主節(jié)點(diǎn)同步數(shù)據(jù),如果Primary
?節(jié)點(diǎn)數(shù)據(jù)量比較大同步時(shí)間會(huì)比較長。而keep
復(fù)制指初始化同步過后,節(jié)點(diǎn)之間的實(shí)時(shí)同步一般是增量同步。
初始化同步有以下兩種情況會(huì)觸發(fā):
- Secondary 第一次加入。
- Secondary 落后的數(shù)據(jù)量超過了 oplog 的大小,這樣也會(huì)被全量復(fù)制。
MongoDB
的Primary
節(jié)點(diǎn)選舉基于心跳觸發(fā)。一個(gè)復(fù)制集N
個(gè)節(jié)點(diǎn)中的任意兩個(gè)節(jié)點(diǎn)維持心跳,每個(gè)節(jié)點(diǎn)維護(hù)其他N-1
個(gè)節(jié)點(diǎn)的狀態(tài)。
心跳檢測:
整個(gè)集群需要保持一定的通信才能知道哪些節(jié)點(diǎn)活著哪些節(jié)點(diǎn)掛掉。mongodb
節(jié)點(diǎn)會(huì)向副本集中的其他節(jié)點(diǎn)每2秒
就會(huì)發(fā)送一次pings
包,如果其他節(jié)點(diǎn)在10秒鐘
之內(nèi)沒有返回就標(biāo)示為不能訪問。每個(gè)節(jié)點(diǎn)內(nèi)部都會(huì)維護(hù)一個(gè)狀態(tài)映射表,表明當(dāng)前每個(gè)節(jié)點(diǎn)是什么角色、日志時(shí)間戳等關(guān)鍵信息。如果主節(jié)點(diǎn)發(fā)現(xiàn)自己無法與大部分節(jié)點(diǎn)通訊則把自己降級(jí)為secondary
只讀節(jié)點(diǎn)。
主節(jié)點(diǎn)選舉觸發(fā)的時(shí)機(jī):
第一次初始化一個(gè)副本集
Secondary
節(jié)點(diǎn)權(quán)重比Primary
節(jié)點(diǎn)高時(shí),發(fā)起替換選舉
Secondary
節(jié)點(diǎn)發(fā)現(xiàn)集群中沒有Primary
時(shí),發(fā)起選舉
Primary
節(jié)點(diǎn)不能訪問到大部分(Majority
)成員時(shí)主動(dòng)降級(jí)
當(dāng)觸發(fā)選舉時(shí),Secondary
節(jié)點(diǎn)嘗試將自身選舉為Primary
。主節(jié)點(diǎn)選舉是一個(gè)二階段過程+多數(shù)派協(xié)議。
第一階段:
檢測自身是否有被選舉的資格,如果符合資格會(huì)向其它節(jié)點(diǎn)發(fā)起本節(jié)點(diǎn)是否有選舉資格的?FreshnessCheck
,進(jìn)行同僚仲裁。
第二階段:
發(fā)起者向集群中存活節(jié)點(diǎn)發(fā)送Elect
(選舉)請(qǐng)求,仲裁者收到請(qǐng)求的節(jié)點(diǎn)會(huì)執(zhí)行一系列合法性檢查,如果檢查通過,則仲裁者(一個(gè)復(fù)制集中最多50
個(gè)節(jié)點(diǎn),其中只有7個(gè)具有投票權(quán))給發(fā)起者投一票。
pv0
通過30
秒選舉鎖防止一次選舉中兩次投票。
pv1
使用了terms
(一個(gè)單調(diào)遞增的選舉計(jì)數(shù)器)來防止在一次選舉中投兩次票的情況。
多數(shù)派協(xié)議:
發(fā)起者如果獲得超過半數(shù)的投票,則選舉通過,自身成為Primary
節(jié)點(diǎn)。獲得低于半數(shù)選票的原因,除了常見的網(wǎng)絡(luò)問題外,相同優(yōu)先級(jí)的節(jié)點(diǎn)同時(shí)通過第一階段的同僚仲裁并進(jìn)入第二階段也是一個(gè)原因。因此,當(dāng)選票不足時(shí),會(huì)sleep[0,1]
秒內(nèi)的隨機(jī)時(shí)間,之后再次嘗試選舉。
四、分片模式
4.1 什么是分片
分片 (sharding
) 是MongoDB
用來將大型集合水平分割到不同服務(wù)器(或者副本集)上所采用的方法。 不需要功能強(qiáng)大的大型計(jì)算機(jī)就可以存儲(chǔ)更多的數(shù)據(jù),處理更大的負(fù)載。
4.2 為什么要分片
- 存儲(chǔ)容量需求超出單機(jī)磁盤容量。
- 活躍的數(shù)據(jù)集超出單機(jī)內(nèi)存容量,導(dǎo)致很多請(qǐng)求都要從磁盤讀取數(shù)據(jù),影響性能。
IOPS
超出單個(gè)MongoDB
節(jié)點(diǎn)的服務(wù)能力,隨著數(shù)據(jù)的增長,單機(jī)實(shí)例的瓶頸會(huì)越來越明顯。- 副本集具有節(jié)點(diǎn)數(shù)量限制。
垂直擴(kuò)展
:增加更多的CPU和存儲(chǔ)資源來擴(kuò)展容量。水平擴(kuò)展
:將數(shù)據(jù)集分布在多個(gè)服務(wù)器上,水平擴(kuò)展即分片。
4.3 分片的工作原理
整體架構(gòu)圖:
詳細(xì)架構(gòu)圖:
分片集群由以下3個(gè)服務(wù)組成:
Router Server
: 數(shù)據(jù)庫集群的請(qǐng)求入口,所有請(qǐng)求都通過Router
(mongos
)進(jìn)行協(xié)調(diào),不需要在應(yīng)用程序添加一個(gè)路由選擇器,Router
(mongos
)就是一個(gè)請(qǐng)求分發(fā)中心它負(fù)責(zé)把應(yīng)用程序的請(qǐng)求轉(zhuǎn)發(fā)到對(duì)應(yīng)的?Shard
服務(wù)器上。Shards Server
: 每個(gè)shard
由一個(gè)或多個(gè)mongod
進(jìn)程組成,用于存儲(chǔ)數(shù)據(jù)。Config Server
: 配置服務(wù)器。存儲(chǔ)所有數(shù)據(jù)庫元信息(路由、分片)的配置。
4.3.1 片鍵(shard key)
為了在數(shù)據(jù)集合中分配文檔,MongoDB使用分片主鍵分割集合。
4.3.2 區(qū)塊(chunk)
在一個(gè)shard server
內(nèi)部,MongoDB
還是會(huì)把數(shù)據(jù)分為chunks
,每個(gè)chunk
代表這個(gè)shard server
內(nèi)部一部分?jǐn)?shù)據(jù)。MongoDB
分割分片數(shù)據(jù)到區(qū)塊,每一個(gè)區(qū)塊包含基于分片主鍵的左閉右開的區(qū)間范圍。
4.3.3 分片策略
4.3.3.1 hash分片(Hashed Sharding)
把 Key 作為輸入,輸入到一個(gè) Hash 函數(shù)中,計(jì)算出一個(gè)整數(shù)值,值的集合形成了一個(gè)值域,我們按照固定步長去切分這個(gè)值域,每一個(gè)片叫做 Chunk ,這里的 Chunk 則就是整數(shù)的一段范圍而已。
優(yōu)點(diǎn):
- 計(jì)算速度快
- 均衡性好,純隨機(jī)
缺點(diǎn):
- 正因?yàn)榧冸S機(jī),排序列舉的性能極差,比如你如果按照 name 這個(gè)字段去列舉數(shù)據(jù),你會(huì)發(fā)現(xiàn)幾乎所有的 Shard 都要參與進(jìn)來;
4.3.3.2 范圍分片(Ranged Sharding)
優(yōu)點(diǎn):
- 對(duì)排序列舉場景非常友好,因?yàn)閿?shù)據(jù)本來就是按照順序依次放在 Shard 上的,排序列舉的時(shí)候,順序讀即可,非常快速;
缺點(diǎn):
- 容易導(dǎo)致熱點(diǎn),舉個(gè)例子,如果 Sharding Key 都有相同前綴,那么大概率會(huì)分配到同一個(gè) Shard 上,就盯著這個(gè) Shard 寫,其他 Shard 空閑的很,卻幫不上忙;
4.3.3.3 zone 分片(Zones in Sharded Clusters)
簡單來說 Zone 實(shí)際上像是范圍分片的另一個(gè)版本,你為一定范圍內(nèi)的片鍵制定一個(gè) Zone,然后再將一些分片加入到這個(gè) Zone 中,于是這一范圍內(nèi)的數(shù)據(jù)最終就將存儲(chǔ)在這個(gè) Zone 中的分片上。
五、總結(jié)
本文介紹了 3 種 MongoDB 的高可用架構(gòu),Master-Slave 模式,Replica Set 模式,Sharding 模式,這也是常見的架構(gòu)演進(jìn)的過程,是不是有點(diǎn)恍惚,Redis 也是類似這種架構(gòu)的演進(jìn)。
- MongoDB Master-Slave 已經(jīng)不推薦,甚至新版已經(jīng)不支持這種冗余模式;
- Replica Set 通過數(shù)據(jù)多副本,組件冗余提高了可靠性,并且通過分布式自動(dòng)選主算法,減少了停服時(shí)間窗,提高了可用性;
- Sharding 模式通過橫向擴(kuò)容的方式,為用戶提供了近乎無限的空間;
- MongoDB 客戶端掌握了很大的配置權(quán)限,通過指定寫多數(shù)策略和 strong 模式(只從主節(jié)點(diǎn)讀數(shù)據(jù))能保證數(shù)據(jù)的高可靠和強(qiáng)一致性;