MongoDB学习笔记(三)-----集群架构
MongoDB 有三種集群部署模式,分別為主從復(fù)制(Master-Slaver)、副本集(Replica Set)和分片(Sharding)模式。
- Master-Slaver 是一種主從副本的模式,目前已經(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ù)制
主從復(fù)制是 MongoDB 中最簡單的數(shù)據(jù)庫同步備份的集群技術(shù),其基本的設(shè)置方式是建立一個(gè)主節(jié)點(diǎn)(Primary)和一個(gè)或多個(gè)從節(jié)點(diǎn)(Secondary),如下圖所示。
這種方式比單節(jié)點(diǎn)的可用性好很多,可用于備份、故障恢復(fù)、讀擴(kuò)展等。集群中的主從節(jié)點(diǎn)均運(yùn)行 MongoDB 實(shí)例,完成數(shù)據(jù)的存儲(chǔ)、查詢與修改操作。
主從復(fù)制模式的集群中只能有一個(gè)主節(jié)點(diǎn),主節(jié)點(diǎn)提供所有的增、刪、查、改服務(wù),從節(jié)點(diǎn)不提供任何服務(wù),但是可以通過設(shè)置使從節(jié)點(diǎn)提供查詢服務(wù),這樣可以減少主節(jié)點(diǎn)的壓力。
另外,每個(gè)從節(jié)點(diǎn)要知道主節(jié)點(diǎn)的地址,主節(jié)點(diǎn)記錄在其上的所有操作,從節(jié)點(diǎn)定期輪詢主節(jié)點(diǎn)獲取這些操作,然后對自己的數(shù)據(jù)副本執(zhí)行這些操作,從而保證從節(jié)點(diǎn)的數(shù)據(jù)與主節(jié)點(diǎn)一致。
在主從復(fù)制的集群中,當(dāng)主節(jié)點(diǎn)出現(xiàn)故障時(shí),只能人工介入,指定新的主節(jié)點(diǎn),從節(jié)點(diǎn)不會(huì)自動(dòng)升級(jí)為主節(jié)點(diǎn)。同時(shí),在這段時(shí)間內(nèi),該集群架構(gòu)只能處于只讀狀態(tài)。
副本集
副本集的集群架構(gòu)如下圖所示。
Mongodb(M)表示主節(jié)點(diǎn),Mongodb(S)表示備節(jié)點(diǎn),Mongodb(A)表示仲裁節(jié)點(diǎn)。主備節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù),仲裁節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù)。客戶端同時(shí)連接主節(jié)點(diǎn)與備節(jié)點(diǎn),不連接仲裁節(jié)點(diǎn)。
默認(rèn)設(shè)置下,主節(jié)點(diǎn)提供所有增刪查改服務(wù),備節(jié)點(diǎn)不提供任何服務(wù)。但是可以通過設(shè)置使備節(jié)點(diǎn)提供查詢服務(wù),這樣就可以減少主節(jié)點(diǎn)的壓力,當(dāng)客戶端進(jìn)行數(shù)據(jù)查詢時(shí),請求自動(dòng)轉(zhuǎn)到備節(jié)點(diǎn)上。這個(gè)設(shè)置叫做Read Preference Modes,同時(shí)Java客戶端提供了簡單的配置方式,可以不必直接對數(shù)據(jù)庫進(jìn)行操作。
仲裁節(jié)點(diǎn)是一種特殊的節(jié)點(diǎn),它本身并不存儲(chǔ)數(shù)據(jù),主要的作用是決定哪一個(gè)備節(jié)點(diǎn)在主節(jié)點(diǎn)掛掉之后提升為主節(jié)點(diǎn),所以客戶端不需要連接此節(jié)點(diǎn)。這里雖然只有一個(gè)備節(jié)點(diǎn),但是仍然需要一個(gè)仲裁節(jié)點(diǎn)來提升備節(jié)點(diǎn)級(jí)別。
相信大家看到這里是不是可以聯(lián)想到redis的一種集群模式,即哨兵模式跟這個(gè)原理很像,確實(shí)如此,仲裁節(jié)點(diǎn)就像是一個(gè)哨兵,當(dāng)監(jiān)聽到其它的某個(gè)節(jié)點(diǎn)掛了,會(huì)重新選擇某個(gè)節(jié)點(diǎn)提升為主節(jié)點(diǎn)繼續(xù)對外提供讀寫服務(wù),從而保障集群的高可用性,減少人工干預(yù);
MongoDB復(fù)制原理
mongodb的復(fù)制至少需要兩個(gè)節(jié)點(diǎn)。其中一個(gè)是主節(jié)點(diǎn),負(fù)責(zé)處理客戶端請求,其余的都是從節(jié)點(diǎn),負(fù)責(zé)復(fù)制主節(jié)點(diǎn)上的數(shù)據(jù)。
mongodb各個(gè)節(jié)點(diǎn)常見的搭配方式為:一主一從, 一主多從。
主節(jié)點(diǎn)記錄其上的所有操作oplog,從節(jié)點(diǎn)定期輪詢主節(jié)點(diǎn)獲取這些操作,然后對自己的數(shù)據(jù)副本執(zhí)行這些操作。
副本集的特征
- N個(gè)節(jié)點(diǎn)的集群
- 任何節(jié)點(diǎn)可作為主節(jié)點(diǎn)
- 所有寫操作都在主節(jié)點(diǎn)上
- 自動(dòng)故障遷移
- 自動(dòng)恢復(fù)
此集群擁有一個(gè)主節(jié)點(diǎn)和多個(gè)從節(jié)點(diǎn),這一點(diǎn)與主從復(fù)制模式類似,且主從節(jié)點(diǎn)所負(fù)責(zé)的工作也類似,但是副本集與主從復(fù)制的區(qū)別在于:當(dāng)集群中主節(jié)點(diǎn)發(fā)生故障時(shí),副本集可以自動(dòng)投票,選舉出新的主節(jié)點(diǎn),并引導(dǎo)其余的從節(jié)點(diǎn)連接新的主節(jié)點(diǎn),而且這個(gè)過程對應(yīng)用是透明的。
可以說,MongoDB 的副本集是自帶故障轉(zhuǎn)移功能的主從復(fù)制。
MongoDB 副本集使用的是 N 個(gè) mongod 節(jié)點(diǎn)構(gòu)建的具備自動(dòng)容錯(cuò)功能、自動(dòng)恢復(fù)功能的高可用方案。在副本集中,任何節(jié)點(diǎn)都可作為主節(jié)點(diǎn),但為了維持?jǐn)?shù)據(jù)一致性,只能有一個(gè)主節(jié)點(diǎn)。
主節(jié)點(diǎn)負(fù)責(zé)數(shù)據(jù)的寫入和更新,并在更新數(shù)據(jù)的同時(shí),將操作信息寫入名為 oplog 的日志文件當(dāng)中。主節(jié)點(diǎn)還負(fù)責(zé)指定其他節(jié)點(diǎn)為從節(jié)點(diǎn),并設(shè)置從節(jié)點(diǎn)數(shù)據(jù)的可讀性,從而讓從節(jié)點(diǎn)來分擔(dān)集群讀取數(shù)據(jù)的壓力。
另外,從節(jié)點(diǎn)會(huì)定時(shí)輪詢讀取 oplog 日志,根據(jù)日志內(nèi)容同步更新自身的數(shù)據(jù),保持與主節(jié)點(diǎn)一致。
在一些場景中,用戶還可以使用副本集來擴(kuò)展讀性能,客戶端有能力發(fā)送讀寫操作給不同的服務(wù)器,也可以在不同的數(shù)據(jù)中心獲取不同的副本來擴(kuò)展分布式應(yīng)用的能力。
在副本集中還有一個(gè)額外的仲裁節(jié)點(diǎn)(不需要使用專用的硬件設(shè)備),負(fù)責(zé)在主節(jié)點(diǎn)發(fā)生故障時(shí),參與選舉新節(jié)點(diǎn)作為主節(jié)點(diǎn)。
副本集中的各節(jié)點(diǎn)會(huì)通過心跳信息來檢測各自的健康狀況,當(dāng)主節(jié)點(diǎn)出現(xiàn)故障時(shí),多個(gè)從節(jié)點(diǎn)會(huì)觸發(fā)一次新的選舉操作,并選舉其中一個(gè)作為新的主節(jié)點(diǎn)。為了保證選舉票數(shù)不同,副本集的節(jié)點(diǎn)數(shù)保持為奇數(shù)。
下面我們在三臺(tái)虛擬機(jī)上模式搭建一下mongodb的這種副本集模式的集群;
1、環(huán)境準(zhǔn)備,我這里提前準(zhǔn)備好了三臺(tái)虛擬機(jī),
192.168.111.134
192.168.9.147
192.168.111.133
2、上傳mongodb的安裝包
我這里放在 /usr/local 目錄下, tar -zxvf mongodb-linux-x86_64-4.0.9.tgz
3、為使用方便,將解壓后的文件命名為mongodb
mv mongodb-linux-x86_64-4.0.9 mongodb
4、創(chuàng)建相關(guān)目錄
mkdir data mkdir logs mkdir conf cd logs touch master.log cd conf touch mongodb.conf5、創(chuàng)建配置文件
進(jìn)入conf目錄,創(chuàng)建mongodb.conf,并編輯
6、以上是在主節(jié)點(diǎn)做的操作,在另外的兩個(gè)節(jié)點(diǎn)上做同樣的配置即可,只需要修改端口號(hào)和相應(yīng)的目錄文件地址,下面帖上配置文件
7、做完了上述的配置基本上就可以了,下面我們就來啟動(dòng)集群
進(jìn)入三個(gè)節(jié)點(diǎn)的bin目錄下,執(zhí)行,看到如下信息就表示啟動(dòng)成功了,三個(gè)節(jié)點(diǎn)做同樣的啟動(dòng)操作,
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb.conf
8.配置主、備、仲裁節(jié)點(diǎn)
#連接到節(jié)點(diǎn)
./mongo 192.168.111.133:27017
忽略啟動(dòng)的警告信息,沒有報(bào)錯(cuò)就是連接上了客戶端,
初始化并建立三個(gè)節(jié)點(diǎn)之間的信息,使用如下命令,大家修改為自己機(jī)器的IP
cfg={ _id:“test”, members:[ {_id:0,host:‘192.168.111.133:27017’,priority:2}, {_id:1,host:‘192.168.9.147:27017’,priority:1}, {_id:2,host:‘192.168.111.134:27018’,arbiterOnly:true}] };
可以看到,各個(gè)節(jié)點(diǎn)的基本信息已經(jīng)展示出來了,接著執(zhí)行,
rs.initiate(cfg);
最后,執(zhí)行rs.status();查看集群的狀態(tài)
各個(gè)節(jié)點(diǎn)的狀態(tài)比如節(jié)點(diǎn)的健康狀況,是否主節(jié)點(diǎn)等都可以清楚的看出來
分片
相關(guān)概念
在搭建集群之前,需要首先了解幾個(gè)概念:路由,分片、副本集、配置服務(wù)器等。
- mongos,數(shù)據(jù)庫集群請求的入口,所有的請求都通過mongos進(jìn)行協(xié)調(diào),不需要在應(yīng)用程序添加一個(gè)路由選擇器,mongos自己就是一個(gè)請求分發(fā)中心,它負(fù)責(zé)把對應(yīng)的數(shù)據(jù)請求請求轉(zhuǎn)發(fā)到對應(yīng)的shard服務(wù)器上。在生產(chǎn)環(huán)境通常有多mongos作為請求的入口,防止其中一個(gè)掛掉所有的mongodb請求都沒有辦法操作。
- config server,顧名思義為配置服務(wù)器,存儲(chǔ)所有數(shù)據(jù)庫元信息(路由、分片)的配置。mongos本身沒有物理存儲(chǔ)分片服務(wù)器和數(shù)據(jù)路由信息,只是緩存在內(nèi)存里,配置服務(wù)器則實(shí)際存儲(chǔ)這些數(shù)據(jù)。mongos第一次啟動(dòng)或者關(guān)掉重啟就會(huì)從 config server 加載配置信息,以后如果配置服務(wù)器信息變化會(huì)通知到所有的 mongos 更新自己的狀態(tài),這樣 mongos 就能繼續(xù)準(zhǔn)確路由。在生產(chǎn)環(huán)境通常有多個(gè) config server 配置服務(wù)器,因?yàn)樗鎯?chǔ)了分片路由的元數(shù)據(jù),防止數(shù)據(jù)丟失!
- shard,分片(sharding)是指將數(shù)據(jù)庫拆分,將其分散在不同的機(jī)器上的過程。將數(shù)據(jù)分散到不同的機(jī)器上,不需要功能強(qiáng)大的服務(wù)器就可以存儲(chǔ)更多的數(shù)據(jù)和處理更大的負(fù)載。基本思想就是將集合切成小塊,這些塊分散到若干片里,每個(gè)片只負(fù)責(zé)總數(shù)據(jù)的一部分,最后通過一個(gè)均衡器來對各個(gè)分片進(jìn)行均衡(數(shù)據(jù)遷移)。
- replica set,中文翻譯副本集,其實(shí)就是shard的備份,防止shard掛掉之后數(shù)據(jù)丟失。復(fù)制提供了數(shù)據(jù)的冗余備份,并在多個(gè)服務(wù)器上存儲(chǔ)數(shù)據(jù)副本,提高了數(shù)據(jù)的可用性, 并可以保證數(shù)據(jù)的安全性。
- 仲裁者(Arbiter),是復(fù)制集中的一個(gè)MongoDB實(shí)例,它并不保存數(shù)據(jù)。仲裁節(jié)點(diǎn)使用最小的資源并且不要求硬件設(shè)備,不能將Arbiter部署在同一個(gè)數(shù)據(jù)集節(jié)點(diǎn)中,可以部署在其他應(yīng)用服務(wù)器或者監(jiān)視服務(wù)器中,也可部署在單獨(dú)的虛擬機(jī)中。為了確保復(fù)制集中有奇數(shù)的投票成員(包括primary),需要添加仲裁節(jié)點(diǎn)做為投票,否則primary不能運(yùn)行時(shí)不會(huì)自動(dòng)切換primary。
簡單了解之后,我們可以這樣總結(jié)一下,應(yīng)用請求mongos來操作mongodb的增刪改查,配置服務(wù)器存儲(chǔ)數(shù)據(jù)庫元信息,并且和mongos做同步,數(shù)據(jù)最終存入在shard(分片)上,為了防止數(shù)據(jù)丟失同步在副本集中存儲(chǔ)了一份,仲裁在數(shù)據(jù)存儲(chǔ)到分片的時(shí)候決定存儲(chǔ)到哪個(gè)節(jié)點(diǎn)。
分片架構(gòu)說明
更詳細(xì)點(diǎn)可以看作為:
我上面建立的這個(gè)集群一共使用了8臺(tái)物理服務(wù)器。最左邊三臺(tái)物理服務(wù)器中,每臺(tái)物理服務(wù)器里放一個(gè)config(mongod)進(jìn)程,和一個(gè)mongos進(jìn)程。三個(gè)config節(jié)點(diǎn)組成config副本集,這樣任意一個(gè)config掛掉都不會(huì)對整體造成影響。三個(gè)mongos采用相同的配置,在連接mongoDB集群的時(shí)候,將URL寫成
這種模式,由客戶端自動(dòng)的在3個(gè)mongos中選擇一個(gè)連接,并在一個(gè)mongos出故障時(shí)由客戶端自動(dòng)遷移到另一個(gè)mongos上去。這樣就不怕某個(gè)mongos突然掛掉。
下面的操作使用的MongoDB版本為4.0以上
然后是上面三臺(tái)物理服務(wù)器每個(gè)里面都運(yùn)行著一個(gè)mongod進(jìn)程,用來存放真實(shí)的業(yè)務(wù)數(shù)據(jù),這三個(gè)服務(wù)器的mongod均設(shè)置為Master,并且分屬不同的分片,加載不同內(nèi)容的配置文件。
然后我們就有了3個(gè)分片了,然后我們再為每個(gè)分片設(shè)置副本集,組成一個(gè)3x3的集群,即3個(gè)分片,每個(gè)分片里有3個(gè)數(shù)據(jù)副本,防止數(shù)據(jù)丟失。
于是在同一個(gè)機(jī)房或者同城機(jī)房內(nèi)在找一臺(tái)算力和存儲(chǔ)都比Master大一些的兩臺(tái)物理機(jī),每臺(tái)物理機(jī)里執(zhí)行三個(gè)mongod進(jìn)程,分別數(shù)據(jù)分片1,分片2和分片3的Slave。這樣三分片三復(fù)制集的集群就搭建完成了。下面是詳細(xì)步驟
搭建Config節(jié)點(diǎn)復(fù)制集
config節(jié)點(diǎn)有一個(gè)就夠用了,但是為了實(shí)現(xiàn)高可用,我這里使用3臺(tái)物理機(jī)跑三個(gè)config節(jié)點(diǎn),并組成復(fù)制集。
config節(jié)點(diǎn)的配置文件如下
sharding:clusterRole: configsvr replication:replSetName: confset net:port: 7017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/conf/mongod.logstorage:dbPath: /mnt/mongo/confjournal:enabled: trueprocessManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/conf/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfo跑mongod進(jìn)程很方便,只需編寫好一個(gè)簡短的配置文件就可以了,這也是mongodb比mysql方便的地方,即配置文件結(jié)構(gòu)非常簡單,不需要考慮太多。
其中要注意,clusterRole必須填configsvr,這一點(diǎn)與普通的mongod數(shù)據(jù)庫進(jìn)程不一樣。因?yàn)閏onfig節(jié)點(diǎn)雖然也可以當(dāng)做普通的mongo數(shù)據(jù)來使用,但是其最主要的作用不是存儲(chǔ)業(yè)務(wù)數(shù)據(jù),而是與mongos進(jìn)程配合,存儲(chǔ)每個(gè)分片節(jié)點(diǎn)的信息,數(shù)據(jù)分片規(guī)則,和分片后每個(gè)chunk的存儲(chǔ)信息。所以不應(yīng)該在config節(jié)點(diǎn)中存儲(chǔ)任何業(yè)務(wù)數(shù)據(jù)。
replSetName可以自己隨便起,但在三個(gè)config節(jié)點(diǎn)中應(yīng)該保持相同,這樣才能把三個(gè)config節(jié)點(diǎn)添加到同一個(gè)復(fù)制集中去
port就是開放的端口,注意和其他的進(jìn)程不沖突就可以了,我這里三臺(tái)config節(jié)點(diǎn)的配置文件都是一樣的,用的一樣的數(shù)據(jù)庫端口。
systemLog就是配置mongo運(yùn)行時(shí)產(chǎn)生log日志的存放位置,storage里的dbPath就是存放數(shù)據(jù)庫數(shù)據(jù)文件的位置,如果目錄不存在需要手工創(chuàng)建。
在這里要提醒一下,默認(rèn)搭建出來的mongo數(shù)據(jù)庫集群是沒有管理員密碼的,連接也不需要提供用戶名和密碼,非常不安全。所以我們這里先使用mongodb集群密碼驗(yàn)證的方式生成相關(guān)的密鑰。
生成密鑰使用openssl命令即可,如果數(shù)據(jù)庫服務(wù)器本身沒有openssl命令,可以在其他設(shè)備上生成后拷貝過來
openssl rand -base64 741 > /etc/mongo/mongodb-keyfile生成的密鑰大概是下面這個(gè)樣子,懶得生成的同學(xué)可以直接把我下面這個(gè)拷貝過去使用
bJd/FkxJaYfZPL5bbP7eRI2sh8EydhuZa8jXUtzlT+uYz0oKHKhnMBECsX+CZfRG xebslFdXrWdAuhwVvSoFDGtp9o7O9kwJbna0txKxhFfeYcDh5X81hQT7TbflY1oH JVgCFMrfejz9vR5bMa5ieumhDJ0WruvO3y1fvOVZN4/SDkWahxY88mF40GTambGw q6VeIV4aEPOrqDUu7TqTzuaCGZBRd6EQoWGqQ/bsmq8Q37hag8Pdk1dFE0jyUvsA ol00lIFN+49OkTcO/t20/MUae+opcIn8sUtV7a80WyiklH9AxIRR6Xjl/Peb+vbg gsyq2XK3LFqga/WWDY16AYGBBGn53oCxjkmDH+HZ5VL2IlAoEELUIYHKpSiafUCg /fsVloVJh7niZaOsBrsd7ltK3SDeK2BNdtSGFLdRR80CzmYn+CAmcW87pxlhTopQ iqmHbkAL6AwLyDUkuqVjQCExYNT5jOv2UqHwq758m1PRZJrfikBM3m/oiF1j+R7c i8sqz2qHYKyc4C2l3bRM27IIpayJB976CK4a9TOI/qunNLLNlWGcKlJOvHSDbHEN mvFP5AekkL1rhmPLdk8GQdWTPXe52qTHsH10T9okF59r0qnqx3AXsuOTw/AR1r5d qq3ERE/xB/y2mrXVRmkygel6UKwA7q5UjVQt6w0JubnhKWWtb4xVUbvSgHC/M9jY MaVx6B9O4Ga2ENrAGkH/8iRXiR7BlMR9DZeE+QG1vaz35c/Gj74EbqnGrmyCnlNV T+J1ovhPg6q0L4UsPCWoaXCz2d4HOBNr6Tr3sd7L0wB3UdWINXA3kMUqOiUSLpt/ 2VbnETSdLoNWtezzT09SY4wn+N5yvHbZt+ugwB1i62FvNQLx3IIq9sJqIPvR8R3W HlhxiYTWQp9IaKxIuITOZ+eL+ybmym4jGHErfheRFnNq9ywnJt/ZiGoiPB3xWYZl 4qmi9ZRb38MMNI/8wnwVKm5lWYM4把密鑰文件放到相關(guān)目錄后,還需要修改密鑰文件的權(quán)限,否則mongod進(jìn)程會(huì)啟動(dòng)失敗
chown mongod:mongod /etc/mongo/mongodb-keyfile chmod 600 /etc/mongo/mongodb-keyfile然后我們在配置文件上加入下面這幾行,就可以開啟mongodb集群的密碼功能了。注意這個(gè)mongodb-keyfile要保存好,之后所有分片,復(fù)制集的mongod進(jìn)程都要使用同一個(gè)mongodb-keyfile才能建立集群。
然后我們在三個(gè)物理服務(wù)器上建立相同的目錄,主要是數(shù)據(jù)庫數(shù)據(jù)存儲(chǔ)目錄,pid文件目錄,log文件目錄,然后把密鑰文件mongodb-keyfile和mongod配置文件在三臺(tái)服務(wù)器上都拷貝一個(gè),就可以準(zhǔn)備啟動(dòng)了。
假設(shè)我們mongod的配置文件為/etc/mongo/config.conf,那么在三臺(tái)config節(jié)點(diǎn)服務(wù)器上都運(yùn)行
mongod --config /etc/mongo/config.conf啟動(dòng)三個(gè)config節(jié)點(diǎn),然后我們使用mongo命令任意連接其中一個(gè)節(jié)點(diǎn),初始化配置三個(gè)config節(jié)點(diǎn)為一個(gè)復(fù)制集
rs.initiate({_id: "confset",configsvr: true,members: [{ _id : 0, host : "192.168.1.1:7017" },{ _id : 1, host : "192.168.1.2:7017" },{ _id : 2, host : "192.168.1.3:7017" }]} )上面的_id就是前面配置文件中replSetName你起的名字,在三個(gè)config節(jié)點(diǎn)的配置文件中是相同的,這里rs.initiate的命令只需在一個(gè)config節(jié)點(diǎn)中執(zhí)行即可,其他兩個(gè)節(jié)點(diǎn)會(huì)自動(dòng)添加進(jìn)來,無需每個(gè)節(jié)點(diǎn)都執(zhí)行一遍。但前提是你必須在防火墻上打開你設(shè)置的監(jiān)聽端口,上文中是7017,保證三個(gè)節(jié)點(diǎn)可以互相通信
這樣,由三個(gè)mongod組成的復(fù)制集集群就建設(shè)好了,此時(shí)推薦建立root用戶,這樣在開啟了密碼之后,我們就可以方便的對config節(jié)點(diǎn)登錄和修改配置。
此時(shí)要注意添加root用戶的時(shí)機(jī),要在復(fù)制集初始化之后,密鑰配置之前配置。因?yàn)槿绻€沒有初始化集群,那么創(chuàng)建用戶命令就只對一個(gè)節(jié)點(diǎn)生效,需要?jiǎng)?chuàng)建三遍,而如果創(chuàng)建的不一致還會(huì)導(dǎo)致復(fù)制集的問題,所以要先初始化集群。初始化之后如果配置文件中帶著上面講的keyFile: /etc/mongo/mongodb-keyfile來啟動(dòng),那么啟動(dòng)之后仍然沒有權(quán)限創(chuàng)建新用戶,恰當(dāng)?shù)臅r(shí)機(jī)就是一開始不寫keyFile: /etc/mongo/mongodb-keyfile這兩行到配置文件中去,然后初始化集群,創(chuàng)建root用戶,然后把mongod全部kill掉再在配置文件中加入這兩行后重啟mongod
db.createUser({user: "root",pwd: "passwd",roles: [ { role: "root", db: "admin" } ]} )官網(wǎng)的文檔只給了role為userAdminAnyDatabase的用戶,但是這個(gè)用戶的權(quán)限并不大,不能修改集群內(nèi)的配置,所以還是需要root role。
建立一個(gè)分片節(jié)點(diǎn)并組成副本集
有了config節(jié)點(diǎn)之后,下一步就需要建立分片節(jié)點(diǎn),而且為了保證一個(gè)分片里數(shù)據(jù)庫掛掉之后數(shù)據(jù)不丟失,還需要給每個(gè)分片建立一個(gè)復(fù)制集組成集群里的集群,這樣不僅有了多個(gè)數(shù)據(jù)副本,還可以實(shí)現(xiàn)讀寫分離。
首先我們在Shard 1 Master這臺(tái)服務(wù)器上建立第一個(gè)分片的主節(jié)點(diǎn)。同樣我們先建立數(shù)據(jù)庫數(shù)據(jù)存儲(chǔ)目錄,pid文件目錄,log文件目錄,然后把密鑰文件mongodb-keyfile拷貝到/etc/mongo/下,或者其他的什么位置,然后開始編寫mongod的配置文件
sharding:clusterRole: shardsvr replication:replSetName: shard1 net:port: 17017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard1/mongod.logstorage:dbPath: /mnt/mongo/shard1journal:enabled: trueprocessManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard1/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfile此時(shí)clusterRole:要改成shardsvr,這樣才能和config節(jié)點(diǎn),mongos節(jié)點(diǎn)一起組成分片集群。replSetName可以隨便填一個(gè),但是對于分片一和它的幾個(gè)副本都應(yīng)該是相同的名字。分片一和分片二兩個(gè)副本集的replSetName一般為不一樣的,和config節(jié)點(diǎn)的集群也應(yīng)該不一樣。
然后我們就可以啟動(dòng)master了,一般使用mongod用戶啟動(dòng)
mongod --config /etc/mongo/shard1Master.conf然后我們?nèi)チ硗鈨膳_(tái)放Slave節(jié)點(diǎn)的服務(wù)器,編寫slave節(jié)點(diǎn)的配置文件,而且別忘了建立數(shù)據(jù)庫數(shù)據(jù)存儲(chǔ)目錄,pid文件目錄,log文件目錄,然后把密鑰文件mongodb-keyfile拷貝到/etc/mongo/下。
sharding:clusterRole: shardsvr replication:replSetName: shard1 net:port: 17017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard1/mongod.logstorage:dbPath: /mnt/mongo/shard1journal:enabled: truewiredTiger:engineConfig:cacheSizeGB: 4processManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard1/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfile這里要注意,repSetName要和Master節(jié)點(diǎn)填一樣的。在我的集群里,由于有兩臺(tái)服務(wù)器是存放了三個(gè)分片的slave節(jié)點(diǎn)。而在mongodb的內(nèi)存使用規(guī)則中,使用LRU方式,一個(gè)mongod進(jìn)程最多可以使用50%的物理內(nèi)存,所以三個(gè)節(jié)點(diǎn)可分配的內(nèi)存就是150%的物理內(nèi)存,這樣最后肯定會(huì)觸發(fā)OOM,所以在slave節(jié)點(diǎn)的配置文件中,要加上上面的cacheSizeGB,限定最大使用的內(nèi)存數(shù)量,我這里使用的4GB,我的物理服務(wù)器大約有24GB的物理內(nèi)存。
這里順便提一下mongodb的內(nèi)存管理,從MongoDB 3.2版本開始,就開始使用WiredTiger作為默認(rèn)的存儲(chǔ)引擎,下面摘自mongodb的官方document
Starting in MongoDB 3.4, the default WiredTiger internal cache size is the larger of either:50% of (RAM - 1 GB), or 256 MB. For example, on a system with a total of 4GB of RAM the WiredTiger cache will use 1.5GB of RAM (0.5 * (4GB - 1 GB) = 1.5 GB). Conversely, a system with a total of 1.25 GB of RAM will allocate 256 MB to the WiredTiger cache because that is more than half of the total RAM minus one gigabyte (0.5 * (1.25 GB - 1GB) = 128 MB < 256 MB).在實(shí)際應(yīng)用中,發(fā)現(xiàn)這個(gè)存儲(chǔ)引擎特別的牛逼,比如我插入10GB的數(shù)據(jù),只要數(shù)據(jù)量沒有超過上面的內(nèi)存限制,即總物理內(nèi)存-1的一半,那么數(shù)據(jù)再保存在磁盤的同時(shí),還會(huì)保存在內(nèi)存中,如果你的數(shù)據(jù)庫本身不大而物理內(nèi)存特別大的話,那此時(shí)你已經(jīng)有了一個(gè)內(nèi)存型數(shù)據(jù)庫,所有的查詢在內(nèi)存中就可以完成,這樣的掃描速度往往是磁盤的上千倍。性能還是非常恐怖的。
官網(wǎng)文檔還明確的指出,在一個(gè)服務(wù)器有多個(gè)mongod進(jìn)程或者容器中運(yùn)行時(shí),需要設(shè)定cacheSizeGB這個(gè)參數(shù),原文如下
NOTEThe storage.wiredTiger.engineConfig.cacheSizeGB limits the size of the WiredTiger internal cache. The operating system will use the available free memory for filesystem cache, which allows the compressed MongoDB data files to stay in memory. In addition, the operating system will use any free RAM to buffer file system blocks and file system cache.To accommodate the additional consumers of RAM, you may have to decrease WiredTiger internal cache size.The default WiredTiger internal cache size value assumes that there is a single mongod instance per machine. If a single machine contains multiple MongoDB instances, then you should decrease the setting to accommodate the other mongod instances.If you run mongod in a container (e.g. lxc, cgroups, Docker, etc.) that does not have access to all of the RAM available in a system, you must set storage.wiredTiger.engineConfig.cacheSizeGB to a value less than the amount of RAM available in the container. The exact amount depends on the other processes running in the container.然后我們啟動(dòng)Master節(jié)點(diǎn)的mongod,然后啟動(dòng)兩個(gè)slave節(jié)點(diǎn)的mongod,然后使用mongo命令連接master節(jié)點(diǎn),來把這三個(gè)mongod節(jié)點(diǎn)配置成一主兩備的單一分片集群
rs.initiate({_id : "shard1",members: [{ _id : 0, host : "192.168.1.4:17017" },{ _id : 1, host : "192.168.1.5:17017" },{ _id : 2, host : "192.168.1.6:17017" }]} )上面的是最簡單的配置方式,mongodb自己會(huì)決定哪個(gè)節(jié)點(diǎn)是master,哪些是salve,priority默認(rèn)為0,priority越大越有可能成為master,但是你也可用通過傳參數(shù)來手工指定priority,并且在節(jié)點(diǎn)數(shù)多于2的時(shí)候可以選擇一個(gè)節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù)只做仲裁。也就是三副本模式可以改成兩副本+仲裁模式,如下
rs.initiate({_id : "shard1",members: [{ _id : 0, host : "192.168.1.4:17017" ,priority : 2 },{ _id : 1, host : "192.168.1.5:17017" ,priority : 1 },{ _id : 2, host : "192.168.1.6:17017" ,arbiterOnly :true }]} )然后,為了能在集群之后還能登陸進(jìn)節(jié)點(diǎn)修改數(shù)據(jù)庫配置,我們要添加一個(gè)root用戶,注意添加用戶的時(shí)機(jī)應(yīng)該是集群初始化之后,keyFile: /etc/mongo/mongodb-keyfile寫在配置文件之前。等創(chuàng)建完root之后再把keyFile: /etc/mongo/mongodb-keyfile寫入進(jìn)配置文件重啟。
db.createUser({user: "root",pwd: "root",roles: [ { role: "root", db: "admin" } ]} )創(chuàng)建第二個(gè)分片的集群和第三個(gè)分片的集群也大同小異,下面光把配置文件貼出來
shard 2 master 配置文件:
sharding:clusterRole: shardsvr replication:replSetName: shard2 net:port: 27017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard2/mongod.logstorage:dbPath: /mnt/mongo/shard2journal:enabled: trueprocessManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard2/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfileshard 2 兩個(gè)slave節(jié)點(diǎn)配置文件
sharding:clusterRole: shardsvr replication:replSetName: shard2 net:port: 27017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard2/mongod.logstorage:dbPath: /mnt/mongo/shard2journal:enabled: truewiredTiger:engineConfig:cacheSizeGB: 4processManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard2/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfile初始化shard2 復(fù)制集的命令
rs.initiate({_id : "shard2",members: [{ _id : 0, host : "192.168.1.7:27017" },{ _id : 1, host : "192.168.1.5:27017" },{ _id : 2, host : "192.168.1.6:27017" }]} )shard3 master 配置文件:
sharding:clusterRole: shardsvr replication:replSetName: shard3 net:port: 37017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard3/mongod.logstorage:dbPath: /mnt/mongo/shard3journal:enabled: trueprocessManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard3/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfileshard3 兩個(gè)slave節(jié)點(diǎn)配置文件
sharding:clusterRole: shardsvr replication:replSetName: shard3 net:port: 37017bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/shard3/mongod.logstorage:dbPath: /mnt/mongo/shard3journal:enabled: truewiredTiger:engineConfig:cacheSizeGB: 4processManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/shard3/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfile初始化分片3復(fù)制集的命令
rs.initiate({_id : "shard3",members: [{ _id : 0, host : "192.168.1.8:37017" },{ _id : 1, host : "192.168.1.5:37017" },{ _id : 2, host : "192.168.1.6:37017" }]} )注意三個(gè)分片mongod一般采用不同的接口這樣不容易出錯(cuò)。
然后分別在shard2 和shard3創(chuàng)建root用戶,一遍以后登錄調(diào)試。
現(xiàn)在3個(gè)分片,9個(gè)配置文件,9個(gè)mongod進(jìn)程已經(jīng)都啟動(dòng)起來了,現(xiàn)在可以開始把這3個(gè)分片+config節(jié)點(diǎn)集群配置成一個(gè)大集群了。
首先我們編寫mongos的配置文件,這個(gè)配置比起mysql的路由網(wǎng)關(guān)配置簡單太多了,因?yàn)閙ongodb的mongos配置基本全是啟動(dòng)之后在里面配置,不用提前寫進(jìn)配置文件,這一點(diǎn)比mycat要方便很多,修改參數(shù)無需重啟mongos了。
sharding:configDB: confset/192.168.1.1:7017,192.168.1.2:7017,192.168.1.3:7017 net:port: 2000bindIp: 0.0.0.0systemLog:destination: filelogAppend: truepath: /mnt/mongo/mongos/mongod.logprocessManagement:fork: true # fork and run in backgroundpidFilePath: /mnt/mongo/mongos/mongod.pid # location of pidfiletimeZoneInfo: /usr/share/zoneinfosecurity:keyFile: /etc/mongo/mongodb-keyfile同樣的,我們需要建立日志目錄,需要keyfile密鑰文件,但是無需建立數(shù)據(jù)存儲(chǔ)目錄了,因?yàn)閙ongos不會(huì)存儲(chǔ)任何數(shù)據(jù),只做路由轉(zhuǎn)發(fā),而片鍵和chunk存儲(chǔ)的位置等信息都記錄在config節(jié)點(diǎn)上。
在配置文件中需要指明config集群中所有節(jié)點(diǎn)的IP和端口,并且保證網(wǎng)絡(luò)暢通。然后使用mongos命令啟動(dòng)
mongos --config /etc/mongo/mongos.conf啟動(dòng)一個(gè)或者多個(gè)mongos之后,使用mongo命令連接任何一個(gè)mongos,并且建立好root用戶。注意此處可以先不加keyfile把整個(gè)集群創(chuàng)建完成,root用戶建完,然后再每個(gè)節(jié)點(diǎn)修改配置文件加入keyfile,再把整個(gè)集群的所有節(jié)點(diǎn)重啟一遍。
db.createUser({user: "root",pwd: "root",roles: [ { role: "root", db: "admin" } ]} )然后使用root用戶登錄,把三個(gè)分片都添加進(jìn)去,每個(gè)分片添加里面的一個(gè)節(jié)點(diǎn)即可,master和slave都行,因?yàn)閺?fù)制集里任何一個(gè)節(jié)點(diǎn)都是可以的。
sh.addShard( "shard1/192.168.1.4:17017") sh.addShard( "shard2/192.168.1.7:27017") sh.addShard( "shard3/192.168.1.8:37017")至此,我們的3x3集群,既包含復(fù)制集又包含分片的集群就搭建完成了,下一步就是選擇片鍵,然后對collection進(jìn)行切分,這又是一個(gè)很大的話題。
使用如下bash命令即可接入mongos進(jìn)行配置
mongo --port 2000 -u root -p password --authenticationDatabase admin建立好集群之后,使用root用戶登錄,然后就可以使用
rs.status()命令來來查看集群中有哪些分片和數(shù)據(jù)庫了。
注意mongos只需配置一遍,另外兩個(gè)mongos只需按照配置文件啟動(dòng)起來即可,因?yàn)閙ongos會(huì)調(diào)取config節(jié)點(diǎn)提供的信息。
客戶端連接數(shù)據(jù)庫的時(shí)候,可以選擇任意一個(gè)mongos連接,或者只選擇一個(gè),之用URL這種方式連接。URL方式連接的好處就是對于多種語言的驅(qū)動(dòng)程序都能良好的支持,通用性比較高,因?yàn)橛玫絤ongo的場合很多,nodejs,python和JAVA都會(huì)經(jīng)常調(diào)用,如果每種語言寫一套連接方式那就太麻煩了。
下面是我常用的一種URL
mongodb://username:password@192.168.1.1:2000,192.168.1.2:2000,192.168.1.3:2000/數(shù)據(jù)庫名?authSource=admin&readPreference=secondary&maxStalenessSeconds=120&connectTimeoutMS=300000同時(shí)寫明了用戶名密碼,三個(gè)mongos地址,數(shù)據(jù)庫名,用戶驗(yàn)證庫,讀寫分離,超時(shí)時(shí)間等。在python,java,node均有很好的支持。
總結(jié)
以上是生活随笔為你收集整理的MongoDB学习笔记(三)-----集群架构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 图片高斯模糊解决方案
- 下一篇: 电子【4】