MongoDB3.2 集群搭建


一、集群的理論知識

1.1 集群成員 

MongoDB的集群類似於GreenPlum集群,由一個入口節點負責任務分發與結果統計,分片結節負責執行任務。不同GP,多了一個config servers。

集群有三個組件:
A。shards:分片,即數據結點,存儲數據和執行計算。為了保證高可用和數據一致性,生產環境中shards應該做成
        replicasets(防止丟失數據)。集群中有一個primary shards,執行非分片的任務。
B。mongos(query routers):查詢路由,負責client的連接,並把任務分給shards,然后收集結果。一個集群中可以有多個query
         routers(replica sets),以分擔客戶端請求(負載均衡)。
C。config server:配置服務器。保存了集群的元數據(比如數據放在哪個shards上),query router通過config server中的配置信 
      息決定把任務分配到哪個shards上。從3.2開始,config servers可以做成replica sets。
 
集群架構圖:

1.2 數據的分片

MongoDB在集合層面做數據分片,以shard key來分片。
shard key應該是一個索引字段或者復合索引字段。
MongoDB根據shard key創建chunks,然后把chunks均衡的分布在shards上。
兩種分區方式:range和hash.結果全oracle里range分區和hash分區理解一下。
 

1.3 分片的性能

range分片:適合range query,能夠使用批量I/O。但是如果分區鍵不是均勻分布的的,則可能只用到集群中的少數據結點,不能發揮集群的性能。
hash分片:數據平均分布到各個節點上。但是范圍查詢時需要各個節點一起讀,效率比range分片低。
MongoDB支持數據標簽,用戶可以指定某個標簽的數據分布到特定節點上。

1.4數據的平衡

1.4.1 分裂(splite)

    當一個chunk的大小超過chunk的最大值大時,這個chunk會分裂為兩個。該過程只修改元數據,不遷移數據。該過程是后台進程完成,不需要人工執行。chunk默認值64M。
     分裂的特點:
    1)默認的chunk是64M。小的chunk好處是數據平衡性,壞處是經常要做數據平衡。大的chunk則正好相反
    2)只有在insert或者update時才會發生chunk的分裂。如果人為修改chunk的大小,是不會發生分裂的。
    3)某個特定的shard key values的chunk可能大小默認的chunk大小,並且無法分裂
 

1.4.2 平衡(balance)

    如果集群中的某個節點保存的數據太多,就會自動的把數據分配給其它節點。該過程是后台進程完成,不需要人工執行。
在平衡數據時,先從原始節點復制數據到新節點,然后更新復制的數據。只有在平衡完成后,才會刪除原始節點上的數據。如果發生了錯誤,則不影響原始節點數據。
    增加和刪除節點都會造成數據的平衡。
    注意:並非所有的數據不均勻都會自動平衡,一般來說,一個節點可以至少存儲數百個chunk(其它節點可以一個chunk都沒有)而不觸發平衡操作。    所以小數據量沒有必要使用集群。
    數據平衡的特點:
    1)自動化的,默認是開啟的
    2)每次只移動一個chunk,但可能在源上的chunk沒有刪除前就開始新的移動
    3)只有在節點的chunk數量差距非常大的時候才觸發。
        觸發的閥值:
    4)一直遷移到任何兩個節點上的chunk數量相差小於2為止。
    5)如果設置了shard可以使用的磁盤最大小值 ,如果節點的磁盤使用超過了這個值,將不會balance到這個節點上。
    6)平衡完畢后,會修改confige server的信息
    7)_secondaryThrottle默認為true,當定入至少一個secondary。

1.5 config server

1.5.1 config serve配置成replicatsion sets的限制

     config servers配置成replicate sets有以下限制:

        1)沒有仲裁節點
        2)沒有延遲節點

        3)build indexes必須為true

1.5.2 config server的讀寫

    寫:只有集群的元數據發生變化時,才會更新config server的信息。比如加入、刪除節點、分裂chunk。 使用write majority方式寫。
    讀:當mongos程序重啟或集群的元數據發生了變化mongos才會讀取元數據。 使用read majority方式讀。

1.6 系統架構 

1.6.1 用於生產的架構

    用於生產的架構必須要保證數據的冗余,mongos、shards、config server必須要做成replication sets。每個集群都必須有一個獨立的config server(一台config server不能多用)。生產的架構示意:
    說明:
        不做replications set的話,shard節點是沒有數據冗余的功能,如果數據丟失了,就找不回來(此時其它節點可以正常工作)。因此對於生產環境,做復制是十分必要的。同樣,confige server也是一樣,也要做復制。
 

1.6.2. 用於測試的架構

    測試的架構可以不做replication sets,以節省機器為目的,可以把mongos和config server和shards放一起。測試架構示意:

1.7 分片鍵shards key

    分片鍵用於決定數據分布在哪個節點上。 分片鍵中的列必須是index key或者組合index key,分片鍵也可以組合的(比如key(c1,c2))。分片鍵在數據插入后不能改變。

1.7.1 hash 分片

    hash key能夠很好的將數據均勻的分布在不同的節點上。選擇做為hash key的鍵應該有很大的基數,一般將object_id或者timestamp列作為hash 鍵。
    對於空集合,hash 分片會自動的在每個節點上創建兩個chunk,通過修改shardCollection的numInitialChunks參數來決定空集合的chunk個數。
 

1.7.2 分片鍵對性能的影響

     不同的分片鍵到性能有不同的影響。
     1)使用object_id這樣唯一性或者基數很大的鍵做為分布鍵,則所有數據被離散的分布到各個節點上,這樣能顯著的提高集群的寫性能,適合存儲大量數據的場合。
     2) 查詢集群中的數據時,最快的方式是查詢中包含了分片鍵,這樣就能直接定位的到數據所在的節點,否則就要在所有節點上執行全表掃描。對於讀操作,考慮以下兩點:
 A.確定最常用被查詢的列
 B.考慮這些列哪個對於性能影響最大
如果最后選定的這個列基數比較小,那么在分片皺中加入二級鍵,做一二級鍵組成的集合基數小即可(對比oracle中的組合索引)。
 

1.8 集群的高可用

 1.8.1 shards節點

    如果shars節點沒有做replication sets,該節點如果宕機,這部分數據就不可訪問。因此為了業務的持續性,對於shards節點有必要做成replication sets.

1.8.2 config server

   1) 和shards一樣,如果沒有做replication set此時又宕機的話,整個集群都不能用。如果做了replications sets,當其中的一台機宕機后,會自動選出主節點,整個集群還可以用。如果宕機的過多無法選出主節點,整個集群依然可以用(讀寫),但是不能有chunk操作(chunk的創建、移動)。
   2)如果不用replication set用mirror的方式來做配置config server,在confige server宕機后,則需要重啟所有的集群成員來連接鏡像confige server。解決重啟的辦法是配置DNS

1.8.3 mongos

    mongos是應用程序的入口,如果mongos宕機了,應用程序就無法使用集群。因此一般也做也replication Set。mongos使用的資源相對於shards和confige server是最小的,因此可以和應用服務器放一台機上。當mongos宕機修復后,會自動從config server讀取數據.
 

1.9 集群的查詢

1.9.1 查詢路徑

    mongos是應用程序的接口。mongos通過config server中的信息查詢數據在哪個節點從而分配任務。如果結果有中sort(),primary shard會合並shards的數據然后排序返回給mongos再返回給client.limit()操作直接在shards上完成。skip()不會發送給shards來執行。

1.9.2 mongos標識

    應用程序連接到集群后,執行isMaster()命令,返回:
{
"ismaster" : true,
"msg" : "isdbgrid",
"maxBsonObjectSize" : 16777216,
"ok" : 1
}
則表示是mongos。如果msg不是 isdbgrid則不是mongos。
 

二、集群的搭建

2.1集群搭建的步驟

 

2.1.1 配置confige server

    以下代碼是搭建一個三個結點的replication sets的config server:
1).創建replications sets
mongod --configsvr --replSet configReplSet --port <port> --dbpath <path>
或者使用配置文件
sharding:
clusterRole: configsvr
replication:
replSetName: configReplSet
net:
port: <port>
storage:
dbpath: <path>
2).初始化。進入其中一個的mongo shell:
rs.initiate( {
_id: "configReplSet",
configsvr: true,
members: [
{ _id: 0, host: "<host1>:<port1>" },
{ _id: 1, host: "<host2>:<port2>" },
{ _id: 2, host: "<host3>:<port3>" }
]
} )

2.1.2 創建mongos實例(路由實例)

mongos --configdb configReplSet/<cfgsvr1:port1>,<cfgsvr2:port2>,<cfgsvr3:port3>

2.1.3 加入 shards

1)連接mongos實例:
mongo --host <hostname of machine running mongos> --port <port mongos listens on>
2)在其中一台mongos上加入節點:
sh.addShard( "rs1/mongodb0.example.net:27017" )     (replications sets只需要加入rs中一個節點即可)
sh.addShard( "mongodb0.example.net:27017" )           (單機)
可能需要一段時間來遷移數據

2.1.4 設置分片

2.1.4.1 設置數據庫分片
在設置集合分片之前,必須設置要分片的數據庫。連接mongos:
mongo --host <hostname of machine running mongos> --port <port mongos listens on>
執行:
sh.enableSharding("<database>")或者db.runCommand( { enableSharding: <database> } )
2.1.4.2 設置集合分片
1)確定集合的shard key。如果集合已經有數據,那么在shard key上創建index。如果沒有數據,集群會自動為shard key創建索引
2)將集合加入分片
sh.shardCollection("<database>.<collection>", shard-key-pattern)
如:
sh.shardCollection("records.people", { "zipcode": 1, "name": 1 } )  shard key 為zipcode,如果有相同的zipcode再根據name來分
sh.shardCollection("people.addresses", { "state": 1, "_id": 1 } )      同上
sh.shardCollection("assets.chairs", { "type": 1, "_id": 1 } )               同上
sh.shardCollection("events.alerts", { "_id": "hashed" } )                  hash分片

2.1.5 配置鏡像config server

注意:不推薦使用鏡像,請使用replication sets。
在每個config server上啟動mongod實例:
mongod --configsvr --dbpath /data/configdb --port 27019
每個路由節點啟動mongs,--configdb后面的連接字符串要一致
mongos --configdb cfg0.example.net:27019,cfg1.example.net:27019,cfg2.example.net:27019

2.2 實驗

2.2.1實驗環境

node1 192.168.75.10 config server1(configRS 37017)       mongos1( 27017)     shard1(47017)
node2 192.168.75.11 config server2(configRS 37017)       mongos2(27017)     shard2(47017)
node3 192.168.75.12 config server3(configRS 37017)                                        shard3( 47017)
在三台主機上,分別安mongoConfig、 mongoShard 、mongoRouter三個實例

2.2.2.配置config server

1)配置文件
在三台主機配置configution文件:
[root@node1 mongoConfig]# cat mongodb.config
dbpath=/usr/local/mongoConfig/data
logpath=/usr/local/mongoConfig/log/mongo.log
port=37017
fork=true
#master=true
replSet=configRS
configsvr=true
2)在三台機器上啟動config server實例
[root@node1 bin]# ./mongod -f /usr/local/mongoConfig/mongodb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3032
child process started successfully, parent exiting
注意,打開防火牆的37017端口
3)初始化config server
連接到其中一台configer server:
[root@node1 bin]# ./mongo --port 37017
執行以下初始化:
> rs.initiate( {
... _id: "configRS",
... configsvr: true,
... members: [
... { _id: 0, host: "192.168.75.10:37017" },
... { _id: 1, host: "192.168.75.11:37017" },
... { _id: 2, host: "192.168.75.12:37017" }
... ]
... } );
{ "ok" : 1 }

2.2.3.配置mongos

在每台機器上執行:
./mongos --configdb configRS/192.168.75.10:37017,192.168.75.11:37017,192.168.75.12:37017 --port 27017 --fork --logpath=/usr/local/mongoRouter/log/mongo.log

2.2.4.啟動三個shard實例

在三台機器修改配置文件:
[root@node1 mongoShard]# vi mongodb.config
dbpath=/usr/local/mongoShard/data
logpath=/usr/local/mongoShard/log/mongo.log
port=47017
fork=true
在三台機器上啟動實例:
[root@node1 bin]# ./mongod -f /usr/local/mongoShard/mongodb.config
about to fork child process, waiting until server is ready for connections.
forked process: 17508
child process started successfully, parent exiting

2.2.5.將shards加入集群

在一台機器上連接mongos實例
./mongo --port 27017
執行:
sh.addShard( "192.168.75.10:47017" )
sh.addShard( "192.168.75.11:47017" )
sh.addShard( "192.168.75.12:47017" )

2.2.6.將數據庫加入分片

sh.enableSharding("testShards")

2.2.7.將集合加入分片

sh.shardCollection("testShards.test", { "_id": "hashed" });

2.2.8.插入數據

在某個mongos上執行:
mongos> use testShards
switched to db testShards
mongos> show collections;
test
mongos> db.test.insert({"name":"testshrads","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads2","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads3","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads4","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads5","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads6","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads7","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads8","msg":"ok"});
WriteResult({ "nInserted" : 1 })
mongos> db.test.insert({"name":"testshrads9","msg":"ok"});
WriteResult({ "nInserted" : 1 })
 
查看數據:
mongos> db.test.find(); { "_id" : ObjectId("56815a0617de6d7dfc1051b5"), "name" : "testshrads", "msg" : "ok" } { "_id" : ObjectId("56815a0e17de6d7dfc1051b6"), "name" : "testshrads2", "msg" : "ok" } { "_id" : ObjectId("56815a1717de6d7dfc1051b8"), "name" : "testshrads4", "msg" : "ok" } { "_id" : ObjectId("56815a1b17de6d7dfc1051b9"), "name" : "testshrads5", "msg" : "ok" } { "_id" : ObjectId("56815a1e17de6d7dfc1051ba"), "name" : "testshrads6", "msg" : "ok" } { "_id" : ObjectId("56815a2617de6d7dfc1051bc"), "name" : "testshrads8", "msg" : "ok" } { "_id" : ObjectId("56815a1217de6d7dfc1051b7"), "name" : "testshrads3", "msg" : "ok" } { "_id" : ObjectId("56815a2117de6d7dfc1051bb"), "name" : "testshrads7", "msg" : "ok" } { "_id" : ObjectId("56815a2917de6d7dfc1051bd"), "name" : "testshrads9", "msg" : "ok" }
 

2.2.9.測試數據

連接到某個shards上:
#./mongod --port 47017
執行:
> use testShards
switched to db testShards
> db.test.find();
{ "_id" : ObjectId("56815a1217de6d7dfc1051b7"), "name" : "testshrads3", "msg" : "ok" }
{ "_id" : ObjectId("56815a2117de6d7dfc1051bb"), "name" : "testshrads7", "msg" : "ok" }
{ "_id" : ObjectId("56815a2917de6d7dfc1051bd"), "name" : "testshrads9", "msg" : "ok" }
發現數據分片正常.
mongoDB集群搭建完畢。
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM