副本集
什么是副本集?
顧名思義,副本集是一個集合,即MongoDB實例的集合,集合中的每個成員擁有相同的數據集合;一個副本集包含多個數據節點和一個可選的仲裁節點,在數據節點中,只有一個可以作為主節點(Primary Node),其他節點只能是第二節點(Secondary Nodes)。
主節點接收所有的寫操作,一個副本集只能有一個能夠確認寫入的主節點(Primary Node),如下圖:
第二節點復制主節點的操作日志并且將所有的操作應用到自己的數據集合中,復制過程是異步的,如果主節點不可用,一個可以被選舉的第二節點將會被選舉為主節點,所以在副本集中,即使一個或者多個成員沒有正常運行,但整個副本集仍然可以正常工作;主副節點關系如下圖:
在某些情況下(比如受硬件條件所限,只有一個主節點和一個副節點,無法添加更多的副節點),你可以選擇將mongod實例添加進副本集,并作為仲裁者(仲裁者只負責選舉新的主節點,不持有數據),在副本集中,如果主節點與其他節點無法通信的時間超過配置的時間值( electionTimeoutMillis ),那么副本集將視主節點出現故障,此時將會重新選舉一個正常副節點來作為新的主節點,從而讓整個副本集系統正常工作,如下圖:
副本集搭建(文中為三個mongod實例的副本集)
副本集的搭建的步驟為:同時啟動多個mongod實例(可以在一臺服務器上,也可以在不同的服務器上),然后在每個實例的配置文件中配置相應的配置項,最后啟動實例后,登錄并且在做一次配置即可。
注意: 文中都是通過配置文件的方式來啟動mongod實例的,你也可以通過啟動參數來啟動實例,同時本文中的mongod實例是通過supervisor 來管理的,關于如何通過supervisor管理進程,可以自行查閱相關資料或者參考這里
-
在
/usr/local/etc
(目錄根據自己機器的實際情況來選擇)目錄下添加三個mongodb的配置文件,文件名隨意,為了方便起見,這里分別命名為:mongod0.conf
,mongod1.conf
,mongod2.conf
, 如下圖:
文件內容為:
systemLog: destination: file path: "/var/log/mongod0.log" logAppend: true processManagement: fork: false #因為supervisor本身就是以fork的形式啟動進程,所以這里填false pidFilePath: "/var/run/mongod0.pid" net: bindIp: 127.0.0.1 port: 27017 maxIncomingConnections: 2000 storage: dbPath: "/usr/local/mongodb-4.4.5/mongod0/shard0" journal: enabled: true engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 2 security: authorization: disabled replication: oplogSizeMB: 120 replSetName: replica-set
對于每一個配置項,如果不明白每個配置項的釋義,請參考: mongo配置文件 。另外,如果實例在同一臺機器上,則針對每個實例,需要區分path
, pidFilePath
, port
, dbPath
這幾個的配置值,并且每個配置文件中的replSetName
必須相同。
-
添加每一個實例在supervisor中的啟動文件,
mongod0.ini
,mongod1.ini
,mongod2.ini
, 文件內容如下:[program:shard0] command=/usr/local/mongodb-4.4.5/bin/mongod --config /usr/local/etc/mongod0.conf process_name=%(program_name)s numprocs=1 directory=/usr/local/mongodb-4.4.5 autostart=true startretries=3 autorestart=unexpected stopsignal=QUIT user=user stdout_logfile=/var/log/mongod/mongod0.log stderr_logfile=/var/log/mongod/mongod0-err.log
在supervisorctl中執行update,此時三個實例便啟動成功。
-
三個實例啟動成功后,只是啟動了三個獨立的mongod實例,實例之間并沒有形成副本集,此時需要通過mongo客戶端登錄某一個實例,完成最后一步配置。登錄進mongo shell后,依次執行以下命令:
replica-set > mongo --host 127.0.0.1 --port 27017 replica-set > conf = {_id: "replica-set(這個值必須與mongod實例配置文件中的replSetName相同)", members: [{_id: 0, host: "127.0.0.1:27017"}, {_id: 1, host: "127.0.0.1:27018"}, {_id: 2, host: "127.0.0.1:27019"}]} replica-set > rs.initiate(conf)
rs.initiate(conf)
是初始化副本集配置的命令,初始化后副本集才算配置成功,上面初始化的配置是不帶仲裁節點的配置,如果需要仲裁節點,則需要將配置改為: conf = {_id: replica-set, members: [{_id: 0, host: "127.0.0.1:27017"}, {_id: 1, host: "127.0.0.1:27018"}, {_id: 2, host: "127.0.0.1:27019", arbiter: true}]}, 這樣id為2,地址為127.0.0.1:27019
的節點即為仲裁節點,如果不在初始化的時候指定仲裁節點,后期也可以通過mongo客戶端設置。 -
至此,副本集已經搭建完成,可以對副本集的數據分布以及存儲情況進行驗證。在默認情況下,只能在主節點中進行查詢操作,副本集中副節點(Secondary Nodes)是不能執行mongodb查詢命令的,如果需要在副本節點中執行,則需要通過mongo shell登錄主節點,并在客戶端中執行下面的命令:
replica-set(Primary) > mongo --host 127.0.0.1 --port 27017 replica-set(Primary) > rs.slaveOk()
通過Shell客戶端或者代碼向副本集中插入數據,然后查看數據分布情況,是否與預期的一致。同時,如果通過代碼連接mongodb,那么在保持連接的時候,將主節點斷開連接,查看代碼中的mongodb連接是否還存在。
注意: 通過代碼連接副本集時,在連接的URI中填某一個節點即可,不需要每一個節點地址都填寫,如:
mongodb://127.0.0.1:27017/?replicaSet=replica-set;slaveOk=true;w=majority;wtimeoutMS=2000
分片
什么是分片?
分片是將MongoDB中的數據集分割成多個數據片,每片數據存放在不同的MongoDB實例中,可以理解為將一個MongoDB數據集拆分成多個小型數據集,而小數據集分布在相同或者不同的物理機器上,分割只是從物理層面進行分割,邏輯上仍然屬于同一個數據集合。
分片的目的
- 如果不進行分割,則數據庫所有的讀寫操作都在同一個MongoDB實例或者同一臺機器上,對于資源有限(特別是CPU)的服務器來說,隨著數據量增大以及數據IO越來越頻繁,最終將會導致服務器不堪重負。
- 對于大型系統來說,一臺數據庫服務器或者一個數據庫實例無法滿足數據存儲的需求
- 數據分散存儲,可以多個實例同時執行讀寫,滿足更高的并發需求。
搭建分片實例
分片包含三部分, 如下圖所示:
- 分片(Shards):一般來說,分片為一組MongoDB實例的集群,每個分片與副本集結合使用,即每個分片是一組副本集,數據存儲在每一個分片上。
- 配置服務器(Config Servers):配置服務器存儲分片集群的元數據,該元數據反應了所有分片集群的狀態和組件,元數據包含了每個分片上的chunk列表以及定義塊的范圍,配置服務器同樣存儲了權限驗證的配置信息,比如角色權限控制和集群內部驗證設置。MongoDB同樣使用配置服務器來管理分布式鎖。
- 路由器(Mongos):Mongos緩存了配置服務器的元數據信息,并且通過這些數據來將數據讀寫路由到正確的分片上,當配置服務器的元數據有更新時,Mongos同時也會更新緩存。
注意: 不同的分片集群必須使用不同的配置服務器(Config Servers),不能使用同一個配置服務器(Config Servers)
分片實例的搭建與副本集類似,都是配置不同的配置文件,然后啟動相應的實例:
- Shards: 按照架構圖,每個Shards節點可以是單個Mongod實例,也可以是副本集,比如: 每個Shards節點由一個副本集構成,而副本集由3個Mongod實例構成,每個Mongod實例的配置文件如下:
這里只給出了關鍵配置項,其他配置項根據自己的實際情況配置,圖中的replSetName
表示當前實例屬于哪個副本集,該副本集中的每個節點的該配置項必須一致,clusterRole
表示當前節點在分片中的的角色,可選值有: shardsvr
和configsvr
,shardsvr
表示該節點是作為Shards節點提供服務,而configsvr
表示該節點作為Config Server節點提供服務。
- Config Servers: 按照架構圖中所示,Config Servers為一個副本集,配置方式與Shards一樣,不同的是
clusterRole
配置項的值應該配置為configsvr
, 如下圖:
- Mongos: 路由服務器作為分片架構中開放給應用服務器的唯一節點,可以存在多個路由服務器指向同一個分片系統。路由服務器也需要配置啟動項,而啟動項中需要指定對應的配置服務器副本集,如下圖:
-
配置成功后,先啟動Shards節點,然后啟動Config Servers節點,最后啟動Mongos節點,啟動成功后,需要通過Mongo客戶端連接進Mongos,然后執行如下命令添加Shards節點:
sh.addShard("replName/mongodb3.example.net:27327")
至此,分片搭建完成。