日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MongoDB学习笔记(三)-----集群架构

發布時間:2024/1/1 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MongoDB学习笔记(三)-----集群架构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MongoDB 有三種集群部署模式,分別為主從復制(Master-Slaver)、副本集(Replica Set)和分片(Sharding)模式。

  • Master-Slaver 是一種主從副本的模式,目前已經不推薦使用。
  • Replica Set 模式取代了 Master-Slaver 模式,是一種互為主從的關系。Replica Set 將數據復制多份保存,不同服務器保存同一份數據,在出現故障時自動切換,實現故障轉移,在實際生產中非常實用。
  • Sharding 模式適合處理大量數據,它將數據分開存儲,不同服務器保存不同的數據,所有服務器數據的總和即為整個數據集。

主從復制
主從復制是 MongoDB 中最簡單的數據庫同步備份的集群技術,其基本的設置方式是建立一個主節點(Primary)和一個或多個從節點(Secondary),如下圖所示。

這種方式比單節點的可用性好很多,可用于備份、故障恢復、讀擴展等。集群中的主從節點均運行 MongoDB 實例,完成數據的存儲、查詢與修改操作。

主從復制模式的集群中只能有一個主節點,主節點提供所有的增、刪、查、改服務,從節點不提供任何服務,但是可以通過設置使從節點提供查詢服務,這樣可以減少主節點的壓力。

另外,每個從節點要知道主節點的地址,主節點記錄在其上的所有操作,從節點定期輪詢主節點獲取這些操作,然后對自己的數據副本執行這些操作,從而保證從節點的數據與主節點一致。

在主從復制的集群中,當主節點出現故障時,只能人工介入,指定新的主節點,從節點不會自動升級為主節點。同時,在這段時間內,該集群架構只能處于只讀狀態。

副本集

副本集的集群架構如下圖所示。

Mongodb(M)表示主節點,Mongodb(S)表示備節點,Mongodb(A)表示仲裁節點。主備節點存儲數據,仲裁節點不存儲數據。客戶端同時連接主節點與備節點,不連接仲裁節點。

默認設置下,主節點提供所有增刪查改服務,備節點不提供任何服務。但是可以通過設置使備節點提供查詢服務,這樣就可以減少主節點的壓力,當客戶端進行數據查詢時,請求自動轉到備節點上。這個設置叫做Read Preference Modes,同時Java客戶端提供了簡單的配置方式,可以不必直接對數據庫進行操作。

仲裁節點是一種特殊的節點,它本身并不存儲數據,主要的作用是決定哪一個備節點在主節點掛掉之后提升為主節點,所以客戶端不需要連接此節點。這里雖然只有一個備節點,但是仍然需要一個仲裁節點來提升備節點級別。

相信大家看到這里是不是可以聯想到redis的一種集群模式,即哨兵模式跟這個原理很像,確實如此,仲裁節點就像是一個哨兵,當監聽到其它的某個節點掛了,會重新選擇某個節點提升為主節點繼續對外提供讀寫服務,從而保障集群的高可用性,減少人工干預;

MongoDB復制原理
mongodb的復制至少需要兩個節點。其中一個是主節點,負責處理客戶端請求,其余的都是從節點,負責復制主節點上的數據。
mongodb各個節點常見的搭配方式為:一主一從, 一主多從。
主節點記錄其上的所有操作oplog,從節點定期輪詢主節點獲取這些操作,然后對自己的數據副本執行這些操作。

副本集的特征

  • N個節點的集群
  • 任何節點可作為主節點
  • 所有寫操作都在主節點上
  • 自動故障遷移
  • 自動恢復

此集群擁有一個主節點和多個從節點,這一點與主從復制模式類似,且主從節點所負責的工作也類似,但是副本集與主從復制的區別在于:當集群中主節點發生故障時,副本集可以自動投票,選舉出新的主節點,并引導其余的從節點連接新的主節點,而且這個過程對應用是透明的。

可以說,MongoDB 的副本集是自帶故障轉移功能的主從復制。

MongoDB 副本集使用的是 N 個 mongod 節點構建的具備自動容錯功能、自動恢復功能的高可用方案。在副本集中,任何節點都可作為主節點,但為了維持數據一致性,只能有一個主節點。

主節點負責數據的寫入和更新,并在更新數據的同時,將操作信息寫入名為 oplog 的日志文件當中。主節點還負責指定其他節點為從節點,并設置從節點數據的可讀性,從而讓從節點來分擔集群讀取數據的壓力。

另外,從節點會定時輪詢讀取 oplog 日志,根據日志內容同步更新自身的數據,保持與主節點一致。

在一些場景中,用戶還可以使用副本集來擴展讀性能,客戶端有能力發送讀寫操作給不同的服務器,也可以在不同的數據中心獲取不同的副本來擴展分布式應用的能力。

在副本集中還有一個額外的仲裁節點(不需要使用專用的硬件設備),負責在主節點發生故障時,參與選舉新節點作為主節點。

副本集中的各節點會通過心跳信息來檢測各自的健康狀況,當主節點出現故障時,多個從節點會觸發一次新的選舉操作,并選舉其中一個作為新的主節點。為了保證選舉票數不同,副本集的節點數保持為奇數。

下面我們在三臺虛擬機上模式搭建一下mongodb的這種副本集模式的集群;

1、環境準備,我這里提前準備好了三臺虛擬機,

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、創建相關目錄

mkdir data mkdir logs mkdir conf cd logs touch master.log cd conf touch mongodb.conf

5、創建配置文件
進入conf目錄,創建mongodb.conf,并編輯

6、以上是在主節點做的操作,在另外的兩個節點上做同樣的配置即可,只需要修改端口號和相應的目錄文件地址,下面帖上配置文件

#master配置 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/logs/master.log logappend=true bind_ip=192.168.111.133 port=27017 fork=true noprealloc=true replSet=test#slave配置 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/logs/slave.log logappend=true bind_ip=192.168.9.147 port=27017 fork=true noprealloc=true replSet=test#仲裁節點配置 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/logs/arbite.log logappend=true bind_ip=192.168.111.134 port=27018 fork=true noprealloc=true replSet=test

7、做完了上述的配置基本上就可以了,下面我們就來啟動集群

進入三個節點的bin目錄下,執行,看到如下信息就表示啟動成功了,三個節點做同樣的啟動操作,

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb.conf


8.配置主、備、仲裁節點

#連接到節點
./mongo 192.168.111.133:27017

忽略啟動的警告信息,沒有報錯就是連接上了客戶端,

初始化并建立三個節點之間的信息,使用如下命令,大家修改為自己機器的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}] };


可以看到,各個節點的基本信息已經展示出來了,接著執行,
rs.initiate(cfg);


最后,執行rs.status();查看集群的狀態

{"set" : "test","date" : ISODate("2019-06-17T01:34:05.135Z"),"myState" : 2,"term" : NumberLong(0),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"appliedOpTime" : {"ts" : Timestamp(1560735223, 1),"t" : NumberLong(-1)},"durableOpTime" : {"ts" : Timestamp(1560735223, 1),"t" : NumberLong(-1)}},"lastStableCheckpointTimestamp" : Timestamp(0, 0),"members" : [{"_id" : 0,"name" : "192.168.111.133:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 169,"optime" : {"ts" : Timestamp(1560735223, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2019-06-17T01:33:43Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "could not find member to sync from","configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "192.168.9.147:27017","health" : 1,"state" : 0,"stateStr" : "STARTUP","uptime" : 21,"optime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"optimeDurable" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"optimeDate" : ISODate("1970-01-01T00:00:00Z"),"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),"lastHeartbeat" : ISODate("2019-06-17T01:34:04.957Z"),"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),"pingMs" : NumberLong(5),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : -2},{"_id" : 2,"name" : "192.168.111.134:27018","health" : 1,"state" : 0,"stateStr" : "STARTUP","uptime" : 21,"lastHeartbeat" : ISODate("2019-06-17T01:34:04.794Z"),"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),"pingMs" : NumberLong(4),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : -2}],"ok" : 1,"operationTime" : Timestamp(1560735223, 1),"$clusterTime" : {"clusterTime" : Timestamp(1560735223, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}} }

各個節點的狀態比如節點的健康狀況,是否主節點等都可以清楚的看出來

分片

相關概念
在搭建集群之前,需要首先了解幾個概念:路由,分片、副本集、配置服務器等。

  • mongos,數據庫集群請求的入口,所有的請求都通過mongos進行協調,不需要在應用程序添加一個路由選擇器,mongos自己就是一個請求分發中心,它負責把對應的數據請求請求轉發到對應的shard服務器上。在生產環境通常有多mongos作為請求的入口,防止其中一個掛掉所有的mongodb請求都沒有辦法操作。
  • config server,顧名思義為配置服務器,存儲所有數據庫元信息(路由、分片)的配置。mongos本身沒有物理存儲分片服務器和數據路由信息,只是緩存在內存里,配置服務器則實際存儲這些數據。mongos第一次啟動或者關掉重啟就會從 config server 加載配置信息,以后如果配置服務器信息變化會通知到所有的 mongos 更新自己的狀態,這樣 mongos 就能繼續準確路由。在生產環境通常有多個 config server 配置服務器,因為它存儲了分片路由的元數據,防止數據丟失!
  • shard,分片(sharding)是指將數據庫拆分,將其分散在不同的機器上的過程。將數據分散到不同的機器上,不需要功能強大的服務器就可以存儲更多的數據和處理更大的負載。基本思想就是將集合切成小塊,這些塊分散到若干片里,每個片只負責總數據的一部分,最后通過一個均衡器來對各個分片進行均衡(數據遷移)。
  • replica set,中文翻譯副本集,其實就是shard的備份,防止shard掛掉之后數據丟失。復制提供了數據的冗余備份,并在多個服務器上存儲數據副本,提高了數據的可用性, 并可以保證數據的安全性。
  • 仲裁者(Arbiter),是復制集中的一個MongoDB實例,它并不保存數據。仲裁節點使用最小的資源并且不要求硬件設備,不能將Arbiter部署在同一個數據集節點中,可以部署在其他應用服務器或者監視服務器中,也可部署在單獨的虛擬機中。為了確保復制集中有奇數的投票成員(包括primary),需要添加仲裁節點做為投票,否則primary不能運行時不會自動切換primary。

簡單了解之后,我們可以這樣總結一下,應用請求mongos來操作mongodb的增刪改查,配置服務器存儲數據庫元信息,并且和mongos做同步,數據最終存入在shard(分片)上,為了防止數據丟失同步在副本集中存儲了一份,仲裁在數據存儲到分片的時候決定存儲到哪個節點。

分片架構說明

更詳細點可以看作為:

我上面建立的這個集群一共使用了8臺物理服務器。最左邊三臺物理服務器中,每臺物理服務器里放一個config(mongod)進程,和一個mongos進程。三個config節點組成config副本集,這樣任意一個config掛掉都不會對整體造成影響。三個mongos采用相同的配置,在連接mongoDB集群的時候,將URL寫成

mongodb://username:password@192.168.1.1:2000,192.168.1.2:2000,192.168.1.3:2000/DatabaseName

這種模式,由客戶端自動的在3個mongos中選擇一個連接,并在一個mongos出故障時由客戶端自動遷移到另一個mongos上去。這樣就不怕某個mongos突然掛掉。

下面的操作使用的MongoDB版本為4.0以上

然后是上面三臺物理服務器每個里面都運行著一個mongod進程,用來存放真實的業務數據,這三個服務器的mongod均設置為Master,并且分屬不同的分片,加載不同內容的配置文件。

然后我們就有了3個分片了,然后我們再為每個分片設置副本集,組成一個3x3的集群,即3個分片,每個分片里有3個數據副本,防止數據丟失。

于是在同一個機房或者同城機房內在找一臺算力和存儲都比Master大一些的兩臺物理機,每臺物理機里執行三個mongod進程,分別數據分片1,分片2和分片3的Slave。這樣三分片三復制集的集群就搭建完成了。下面是詳細步驟

搭建Config節點復制集

config節點有一個就夠用了,但是為了實現高可用,我這里使用3臺物理機跑三個config節點,并組成復制集。

config節點的配置文件如下

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進程很方便,只需編寫好一個簡短的配置文件就可以了,這也是mongodb比mysql方便的地方,即配置文件結構非常簡單,不需要考慮太多。

其中要注意,clusterRole必須填configsvr,這一點與普通的mongod數據庫進程不一樣。因為config節點雖然也可以當做普通的mongo數據來使用,但是其最主要的作用不是存儲業務數據,而是與mongos進程配合,存儲每個分片節點的信息,數據分片規則,和分片后每個chunk的存儲信息。所以不應該在config節點中存儲任何業務數據。

replSetName可以自己隨便起,但在三個config節點中應該保持相同,這樣才能把三個config節點添加到同一個復制集中去

port就是開放的端口,注意和其他的進程不沖突就可以了,我這里三臺config節點的配置文件都是一樣的,用的一樣的數據庫端口。

systemLog就是配置mongo運行時產生log日志的存放位置,storage里的dbPath就是存放數據庫數據文件的位置,如果目錄不存在需要手工創建。

在這里要提醒一下,默認搭建出來的mongo數據庫集群是沒有管理員密碼的,連接也不需要提供用戶名和密碼,非常不安全。所以我們這里先使用mongodb集群密碼驗證的方式生成相關的密鑰。

生成密鑰使用openssl命令即可,如果數據庫服務器本身沒有openssl命令,可以在其他設備上生成后拷貝過來

openssl rand -base64 741 > /etc/mongo/mongodb-keyfile

生成的密鑰大概是下面這個樣子,懶得生成的同學可以直接把我下面這個拷貝過去使用

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

把密鑰文件放到相關目錄后,還需要修改密鑰文件的權限,否則mongod進程會啟動失敗

chown mongod:mongod /etc/mongo/mongodb-keyfile chmod 600 /etc/mongo/mongodb-keyfile

然后我們在配置文件上加入下面這幾行,就可以開啟mongodb集群的密碼功能了。注意這個mongodb-keyfile要保存好,之后所有分片,復制集的mongod進程都要使用同一個mongodb-keyfile才能建立集群。

然后我們在三個物理服務器上建立相同的目錄,主要是數據庫數據存儲目錄,pid文件目錄,log文件目錄,然后把密鑰文件mongodb-keyfile和mongod配置文件在三臺服務器上都拷貝一個,就可以準備啟動了。

假設我們mongod的配置文件為/etc/mongo/config.conf,那么在三臺config節點服務器上都運行

mongod --config /etc/mongo/config.conf

啟動三個config節點,然后我們使用mongo命令任意連接其中一個節點,初始化配置三個config節點為一個復制集

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你起的名字,在三個config節點的配置文件中是相同的,這里rs.initiate的命令只需在一個config節點中執行即可,其他兩個節點會自動添加進來,無需每個節點都執行一遍。但前提是你必須在防火墻上打開你設置的監聽端口,上文中是7017,保證三個節點可以互相通信

這樣,由三個mongod組成的復制集集群就建設好了,此時推薦建立root用戶,這樣在開啟了密碼之后,我們就可以方便的對config節點登錄和修改配置。

此時要注意添加root用戶的時機,要在復制集初始化之后,密鑰配置之前配置。因為如果還沒有初始化集群,那么創建用戶命令就只對一個節點生效,需要創建三遍,而如果創建的不一致還會導致復制集的問題,所以要先初始化集群。初始化之后如果配置文件中帶著上面講的keyFile: /etc/mongo/mongodb-keyfile來啟動,那么啟動之后仍然沒有權限創建新用戶,恰當的時機就是一開始不寫keyFile: /etc/mongo/mongodb-keyfile這兩行到配置文件中去,然后初始化集群,創建root用戶,然后把mongod全部kill掉再在配置文件中加入這兩行后重啟mongod

db.createUser({user: "root",pwd: "passwd",roles: [ { role: "root", db: "admin" } ]} )

官網的文檔只給了role為userAdminAnyDatabase的用戶,但是這個用戶的權限并不大,不能修改集群內的配置,所以還是需要root role。

建立一個分片節點并組成副本集

有了config節點之后,下一步就需要建立分片節點,而且為了保證一個分片里數據庫掛掉之后數據不丟失,還需要給每個分片建立一個復制集組成集群里的集群,這樣不僅有了多個數據副本,還可以實現讀寫分離。

首先我們在Shard 1 Master這臺服務器上建立第一個分片的主節點。同樣我們先建立數據庫數據存儲目錄,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

此時clusterRole:要改成shardsvr,這樣才能和config節點,mongos節點一起組成分片集群。replSetName可以隨便填一個,但是對于分片一和它的幾個副本都應該是相同的名字。分片一和分片二兩個副本集的replSetName一般為不一樣的,和config節點的集群也應該不一樣。

然后我們就可以啟動master了,一般使用mongod用戶啟動

mongod --config /etc/mongo/shard1Master.conf

然后我們去另外兩臺放Slave節點的服務器,編寫slave節點的配置文件,而且別忘了建立數據庫數據存儲目錄,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節點填一樣的。在我的集群里,由于有兩臺服務器是存放了三個分片的slave節點。而在mongodb的內存使用規則中,使用LRU方式,一個mongod進程最多可以使用50%的物理內存,所以三個節點可分配的內存就是150%的物理內存,這樣最后肯定會觸發OOM,所以在slave節點的配置文件中,要加上上面的cacheSizeGB,限定最大使用的內存數量,我這里使用的4GB,我的物理服務器大約有24GB的物理內存。

這里順便提一下mongodb的內存管理,從MongoDB 3.2版本開始,就開始使用WiredTiger作為默認的存儲引擎,下面摘自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).

在實際應用中,發現這個存儲引擎特別的牛逼,比如我插入10GB的數據,只要數據量沒有超過上面的內存限制,即總物理內存-1的一半,那么數據再保存在磁盤的同時,還會保存在內存中,如果你的數據庫本身不大而物理內存特別大的話,那此時你已經有了一個內存型數據庫,所有的查詢在內存中就可以完成,這樣的掃描速度往往是磁盤的上千倍。性能還是非常恐怖的。

官網文檔還明確的指出,在一個服務器有多個mongod進程或者容器中運行時,需要設定cacheSizeGB這個參數,原文如下

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.

然后我們啟動Master節點的mongod,然后啟動兩個slave節點的mongod,然后使用mongo命令連接master節點,來把這三個mongod節點配置成一主兩備的單一分片集群

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自己會決定哪個節點是master,哪些是salve,priority默認為0,priority越大越有可能成為master,但是你也可用通過傳參數來手工指定priority,并且在節點數多于2的時候可以選擇一個節點不存儲數據只做仲裁。也就是三副本模式可以改成兩副本+仲裁模式,如下

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 }]} )

然后,為了能在集群之后還能登陸進節點修改數據庫配置,我們要添加一個root用戶,注意添加用戶的時機應該是集群初始化之后,keyFile: /etc/mongo/mongodb-keyfile寫在配置文件之前。等創建完root之后再把keyFile: /etc/mongo/mongodb-keyfile寫入進配置文件重啟。

db.createUser({user: "root",pwd: "root",roles: [ { role: "root", db: "admin" } ]} )

創建第二個分片的集群和第三個分片的集群也大同小異,下面光把配置文件貼出來

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-keyfile

shard 2 兩個slave節點配置文件

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 復制集的命令

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-keyfile

shard3 兩個slave節點配置文件

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復制集的命令

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" }]} )

注意三個分片mongod一般采用不同的接口這樣不容易出錯。

然后分別在shard2 和shard3創建root用戶,一遍以后登錄調試。

現在3個分片,9個配置文件,9個mongod進程已經都啟動起來了,現在可以開始把這3個分片+config節點集群配置成一個大集群了。

首先我們編寫mongos的配置文件,這個配置比起mysql的路由網關配置簡單太多了,因為mongodb的mongos配置基本全是啟動之后在里面配置,不用提前寫進配置文件,這一點比mycat要方便很多,修改參數無需重啟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密鑰文件,但是無需建立數據存儲目錄了,因為mongos不會存儲任何數據,只做路由轉發,而片鍵和chunk存儲的位置等信息都記錄在config節點上。

在配置文件中需要指明config集群中所有節點的IP和端口,并且保證網絡暢通。然后使用mongos命令啟動

mongos --config /etc/mongo/mongos.conf

啟動一個或者多個mongos之后,使用mongo命令連接任何一個mongos,并且建立好root用戶。注意此處可以先不加keyfile把整個集群創建完成,root用戶建完,然后再每個節點修改配置文件加入keyfile,再把整個集群的所有節點重啟一遍。

db.createUser({user: "root",pwd: "root",roles: [ { role: "root", db: "admin" } ]} )

然后使用root用戶登錄,把三個分片都添加進去,每個分片添加里面的一個節點即可,master和slave都行,因為復制集里任何一個節點都是可以的。

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集群,既包含復制集又包含分片的集群就搭建完成了,下一步就是選擇片鍵,然后對collection進行切分,這又是一個很大的話題。

使用如下bash命令即可接入mongos進行配置

mongo --port 2000 -u root -p password --authenticationDatabase admin

建立好集群之后,使用root用戶登錄,然后就可以使用

rs.status()

命令來來查看集群中有哪些分片和數據庫了。

注意mongos只需配置一遍,另外兩個mongos只需按照配置文件啟動起來即可,因為mongos會調取config節點提供的信息。

客戶端連接數據庫的時候,可以選擇任意一個mongos連接,或者只選擇一個,之用URL這種方式連接。URL方式連接的好處就是對于多種語言的驅動程序都能良好的支持,通用性比較高,因為用到mongo的場合很多,nodejs,python和JAVA都會經常調用,如果每種語言寫一套連接方式那就太麻煩了。

下面是我常用的一種URL

mongodb://username:password@192.168.1.1:2000,192.168.1.2:2000,192.168.1.3:2000/數據庫名?authSource=admin&readPreference=secondary&maxStalenessSeconds=120&connectTimeoutMS=300000

同時寫明了用戶名密碼,三個mongos地址,數據庫名,用戶驗證庫,讀寫分離,超時時間等。在python,java,node均有很好的支持。

總結

以上是生活随笔為你收集整理的MongoDB学习笔记(三)-----集群架构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。