壹、環境
因為是只是練習環境,我開了4台虛擬機 (com6, com7, com8, com9) 進行測試
作業系統皆為CentOS 7
com6: 192.168.1.1
com7: 192.168.1.2
com8: 192.168.1.3
com9: 192.168.1.4
貳、Sharding Cluster構想
預計由三組Replica Set,一個Config Server,一個Routing Server (mongos) 組成
因此
com6: ("rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019")
com7: ("rs1/192.168.1.2:27017,192.168.1.2:27018,192.168.1.2:27019")
com8: ("rs2/192.168.1.3:27017,192.168.1.3:27018,192.168.1.3:27019")
com9: Config Server: ("192.168.1.4:27017") , Routing Server: ("192.168.1.4:27018")
參、步驟
一、安裝MongoDB
1. MongoDB的官方軟體庫包含有五個軟體包(packages)
(1) mongodb-org 這是一個metapackage,可以透過安裝這個自動安裝其他四個軟體包
(2) mongodb-org-server mongod伺服器與設定檔
(1) mongodb-org 這是一個metapackage,可以透過安裝這個自動安裝其他四個軟體包
(2) mongodb-org-server mongod伺服器與設定檔
(3) mongodb-org-mongos mongos伺服器.
(4) mongodb-org-shell mongo操作介面(shell)
(5) mongodb-org-tools 包括了所有跟mognodb有關的小工具
2. 因為CentOS預設的Yum伺服器中沒有MongoDB軟體庫(Repository)的相關資訊,因此必須先新增Repos設定檔
#vi /etc/yum.repos.d/mongodb-org-3.2.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
3. 新增完之後就可以使用Yum安裝了
#yum install –y mongodb-org
在構想階段,有com6, com7 com8分別為三個MongoDB實體的Replica Set,因此設定設定檔、資料庫目錄、記錄檔共要三組
二、設定MongoDB
在構想階段,有com6, com7 com8分別為三個MongoDB實體的Replica Set,因此設定設定檔、資料庫目錄、記錄檔共要三組
而com9為Config Server與Routing Server所以設定檔跟記錄檔要兩份,但Routing Server本身不儲存任何資料,因此只需要替Config Server建立一個資料庫目錄即可
1. 複製設定檔
com6, com7, com8 都要執行以下指令,將設定檔複製三分,分別為mongod1.conf, mongod2.conf, mongod3,conf
#mv /etc/mongod.conf /etc/mongod1.conf
#cp /etc/mongod1.conf /etc/mongod2.conf
#cp /etc/mongod1.conf /etc/mongod3.conf
com9裡面有兩個MongoDB實體,因此要兩份設定檔,分別為mongod-configserv.conf與mongod-routingserv.conf
#mv /etc/mongod.conf /etc/mongod-configserv.conf
#cp /etc/mongod1.conf
/etc/mongod-routingserv.conf
2. 修改設定檔
2.1. com6, com7, com8設定
#vim /etc/mongod1.conf
修改將第10行的path: /var/log/mongodb/mongod.log
將com6的mongod.log改為mongod1.log
將com7的mongod.log改為mongod1.log
將com8的mongod.log改為mongod1.log
修改第14行的dbPath:
/var/lib/mongo
將com6的mongo改為dbPath: /var/lib/mongo1
將com7的mongo改為dbPath: /var/lib/mongo1
將com8的mongo改為dbPath: /var/lib/mongo1
註解第29行的bindIp: 127.0.0.1
將com6的bindIp註解起來,變為#bindIp
將com7的bindIp註解起來,變為#bindIp
將com8的bindIp註解起來,變為#bindIp
取消第36行#replication的註解
將com6的#replication: 取消註解,變成replication:
將com7的#replication: 取消註解,變成replication:
將com8的#replication: 取消註解,變成replication:
在第37行新增Replica Set的名稱( replSetName: )
com6為 replSetName: rs0
com7為 replSetName: rs1
com8為 replSetName: rs2
注意:replSetName前面空兩格,:後面空一格,不然會報錯
#vim /etc/mongod2.conf
修改將第10行的path: /var/log/mongodb/mongod.log
將com6的mongod.log改為mongod2.log
將com7的mongod.log改為mongod2.log
將com8的mongod.log改為mongod2.log
修改第14行的dbPath: /var/lib/mongo
將com6的mongo改為dbPath: /var/lib/mongo2
將com7的mongo改為dbPath: /var/lib/mongo2
將com8的mongo改為dbPath: /var/lib/mongo2
修改第28行的port: 27017
com6改為port: 27018
com7改為port: 27018
com8改為port: 27018
註解第29行的bindIp: 127.0.0.1
將com6的bindIp註解起來,變為#bindIp
將com7的bindIp註解起來,變為#bindIp
將com8的bindIp註解起來,變為#bindIp
取消第36行#replication的註解
將com6的#replication: 取消註解,變成replication:
將com7的#replication: 取消註解,變成replication:
將com8的#replication: 取消註解,變成replication:
在第37行新增Replica Set的名稱( replSetName: )
com6為 replSetName: rs0
com7為 replSetName: rs1
com8為 replSetName: rs2
注意:replSetName前面空兩格,:後面空一格,不然會報錯
#vim /etc/mongod3.conf
修改將第10行的path: /var/log/mongodb/mongod.log
將com6的mongod.log改為mongod3.log
將com7的mongod.log改為mongod3.log
將com8的mongod.log改為mongod3.log
修改第14行的dbPath: /var/lib/mongo
將com6的mongo改為dbPath: /var/lib/mongo3
將com7的mongo改為dbPath: /var/lib/mongo3
將com8的mongo改為dbPath: /var/lib/mongo3
修改第28行的port: 27017
com6改為port: 27019
com7改為port: 27019
com8改為port: 27019
註解第29行的bindIp: 127.0.0.1
將com6的bindIp註解起來,變為#bindIp
將com7的bindIp註解起來,變為#bindIp
將com8的bindIp註解起來,變為#bindIp
取消第36行#replication的註解
將com6的#replication: 取消註解,變成replication:
將com7的#replication: 取消註解,變成replication:
將com8的#replication: 取消註解,變成replication:
在第37行新增Replica Set的名稱( replSetName: )
com6為 replSetName: rs0
com7為 replSetName: rs1
com8為 replSetName: rs2
注意:replSetName前面空兩格,:後面空一格,不然會報錯
2.2. com9設定
2.2.1. config server
#vim mongo-config.conf
將第10行的path: /var/log/mongodb/mongod 改為path: /var/log/mongodb/mongod-configserv.log
將第14行的dbPath: /var/lib/mongo改為 dbPath: /var/lib/mongo-configserv
將第29行的bindIp: 127.0.0.1註解掉,改為#bindIp: 127.0.0.1
將第38行的#sharding取消註解,變為sharding
在第39行打上
clusterRole: configsvr
(clusterRole前面空兩格,:後空一格,不然會報錯)
2.2.2. routing server(mongos)
#vim /etc/mongo-routingserv.conf
將第10行的path: /var/log/mongodb/mongod 改為path: /var/log/mongodb/mongod-routingserv.log
將13~16行的與storage與旗下之選項全部註解掉
將第28行的,port: 27017改為port: 27018
將第29行的bindIp: 127.0.0.1註解掉,改為#bindIp: 127.0.0.1
將第38行的#sharding取消註解,變為sharding
在第39行打上
configDB: 192.168.1.4:27017
帶第40行打上
chunkSize: 64
(configDB與chunkSize前面空兩格,:後面空一格,不然會報錯)
3. 建立資料庫目錄
3.1. com6, com7, com8
#mv /var/lib/mongo /var/lib/mongo1
#mkdir mongo2
#mkdir mongo3
#chown mongod:mongod mongo2
#chown mongod:mongod mongo3
3.2. com9
#mv /var/lib/mongo /var/lib/mongo-configserv
三、建立Sharding Cluster
1. 建立Replica Set
1.1. 啟動mongod
在com6, com7, com8都要執行mongod
#mongod -f /etc/mongod1.conf
#mongod -f /etc/mongod2.conf
#mongod -f /etc/mongod3.conf
-f 的意思是使用設定檔執行,後面接設定檔路徑
1.2. 初始化Replica Set
假設三組Replica Set皆要以使用27017這個port的mongod作為為Primary
在com6, com7, com8執行mongo客戶端
#mongo --port 27017
--port後面接的port是mongod設定檔中的設定port
所以如果是打27018就是連入使用mongod2.conf這個設定檔的mongod
分別在三台電腦中輸入
>rs.initiate()
輸入完之後如果有顯示{“ok” : 1}表示設定成功
會看到你的輸入欄位由>變為rs0:OTHER>
過幾秒按一下Enter會發現rs0:OTHER>變為rs0>PRIMARY,此時可以知道這個mongod在Replica Set的地位已經是Primary了
1.3. 替mongod加入新成員
在com6中輸入
rs.0:PRIMARY>rs.add(”192.168.1.1:27018”)
rs.0:PRIMARY>rs.add(”192.168.1.1:27019”)
顯示{“ok” : 1}表示新增成功
在com7中輸入
rs.0:PRIMARY>rs.add(”192.168.1.2:27018”)
rs.0:PRIMARY>rs.add(”192.168.1.2:27019”)
顯示{“ok” : 1}表示新增成功
在com8中輸入
rs.0:PRIMARY>rs.add(”192.168.1.3:27018”)
rs.0:PRIMARY>rs.add(”192.168.1.3:27019”)
顯示{“ok” : 1}表示新增成功
新增成功後可以輸入rs.status()查看Replica Set查看狀態
2. Sharding Cluster設定
2.1. 在com9中啟動config server與mongos
#mongod -f /etc/mongod-configserv.conf
#mongos -f /etc/mongod-routingserv.conf
2.2. 將Replica Set轉為Shard
2.2.1. 進入mongos
#mongo --port 27018
2.2.2. 將Replica Set加入Sharding Cluster中
輸入
mongos>sh.shardAdd("rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019”)
回傳{ "shardAdded" : "rs0",
"ok" : 1 }代表成功
mongos>sh.shardAdd("rs1/192.168.1.2:27017,192.168.1.2:27018,192.168.1.2:27019”)
回傳{ "shardAdded" : "rs1",
"ok" : 1 }代表成功
mongos>sh.shardAdd("rs2/192.168.1.3:27017,192.168.1.3:27018,192.168.1.3:27019”)
回傳{ "shardAdded" : "rs2",
"ok" : 1 }代表成功
新增完成後可以輸入
mongos>sh.status()
檢視sharding cluster狀態
做到這邊有三組ReplicaSet作為Shard的Sharding Cluster就建立成功了!!
(導入資料進入Sharding Cluster時,要導入到mongos中)
肆、測試成果
一、Replica Set測試
1. 檢查否有容錯轉移的功能,以rs0為例
關閉Primary的mongod
#mongod -f /etc/mongod1.conf --shutdown
連入使用原先為Primary的mongod
#mongo --port 27017
出現類似以下訊息表示已經成功關閉
exception: connect failed
此時在連上原先為Secondary的mongod
#mongo --port 27018
可以發現輸入指令的地方從原先的 rs0:SECONDARY> 變為 rs0:PRIMARY>
此時再重新啟動剛剛關閉的mongod
#mongod -f /etc/mongod1.conf
連上該mongod
#mongo --port 27017
可以發現輸入指令的地方從原先的 rs0:Primary> 變為 rs0:Secondary>
此時輸入
rs0:SECONDARY>rs.status()
可以發現使用port27018的mongod的"stateStr"已經由"SECONDARY"變為"PRIMARY"
而可以使用port27017的mongod的"stateStr"已經由"PRIMARY"變為"SECONDARY"
證明這個Replica Set具有容錯轉移功能
二、檢查資料是否會正常複製
1. 下載MongoDB所提供的資料及進行測試
#wget https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json
2. 將資料集導入mongod中
#mongoimport --port 27017 --db rstest --collection restaurants --file primer-dataset.json
(只能將資料導入PRIMARY中,在這個例子中,PRIMARY還是port27017這個mongod)
3. 進入PRIMARY
#mongo --port27017
4. 進入導入的資料庫
rs1:PRIMARY>use rstest
5. 查看資料表是否有導入成功
rs1:PRIMARY>show collections
有顯示restaurants表示導入成功
6. 查看資料表內容
rs1:PRIMARY>db.restaurants.find()
7.離開mongo shell
方法a: Ctrl+C
方法b: rs1:PRIMARY>exit
7. 看看其他Replica Set中的mongod是否有相同的資料
#mongo --port 27018
8. 查看資料庫
rs1:SECONDARY>show databases
此時會報錯
Error: error: { "ok" : 0,
"errmsg" : "not master and slaveOk=false", "code"
: 13435 }
原因在此處有詳細的說明
請注意在預設的情況下,即使連結到 Secondary 節點也無法進行查詢的指令,必須透過 rs.slaveOk() 的指令才能宣告此一連線可用來進行查詢,此一設計的目的是為了避免程式誤連到 Secondary 後而不自知。因為 Secondary 節點與 Primary 節點內的資料存在一段的時間差,因此兩邊的資料可能不完全一致,這個現象對於某些應用來說將導致嚴重的不良後果,所以才需透過這種方式來確認程式的意圖。9. 執行slaveOk
rs1:SECONDARY>rslaveOk()
10. 此時就可以在Secondary執行與Primary相同的查詢
如果查詢發現結果與Primary相同,表示資料可以成功的自動複製
三、測試Sharding Cluster是否會正確切碎資料
1. 下載免費資料集並解壓縮#wget http://jsonstudio.com/wp-content/uploads/2014/02/companies.zip
#unzip companies.zip
2. 導入資料到mongos(因為在sharding cluster中,mongos負責傳遞所有的請求)
#mongoimport --host 192.168.1.4 --port 27018 --db shtest --collection companies --file companies.json
3. 進入mongos並執行sh.status()
#mongo --port 27018
mongos>sh.status()
可以看到顯示的信息有這樣的東西
databases:
{ "_id" : "shtest", "primary" : "rs2", "partitioned" : false }
4. 讓shtest這個資料庫可以被切割
mongos>sh.enableSharding("shtest")
Enables sharding on the specified database. This does not automatically shard any collections but makes it possible to begin sharding collections using sh.shardCollection().透過官方解釋可以得知,這個指令並不會讓資料庫裡面的資料表被切割,透過這個指令只是允許透過sh.shardCollection()來讓資料表可以開始被切割
5. 建立資料表索引
mongos>db.companies.ensureIndex({_id:"hashed"})
官方說明中寫道db.collection.ensureIndex()在3.0版後已經被較新的db.collection.createIndex()取代,但是使用較新的反而會無法切割成功,這點我還在研究
6. 開始切割
mongos>sh.shardCollection("shtest.companies", { "_id": "hashed" } )
7. 確認碎片狀態
mongos>sh.status()
可以看到以下訊息
shtest.companies
shard key: { "_id" : "hashed" }
unique: false
balancing: true
chunks:
rs0 1
rs1 1
rs2 1
{ "_id" : { "$minKey" : 1 } } -->> { "_id" : NumberLong("-591762798808544439") } on : rs0 Timestamp(2, 0)
{ "_id" : NumberLong("-591762798808544439") } -->> { "_id" : NumberLong("7934911588406832349") } on : rs2 Timestamp(3, 0)
{ "_id" : NumberLong("7934911588406832349") } -->> { "_id" : { "$maxKey" : 1 } } on : rs1 Timestamp(3, 1)
可以看出每一個Replica Set都已經獲得了一份切片,同時還會告訴用戶哪部分的切片在哪裡
伍、MongoDB相關指令
執行mongod
#mongod -f /etc/mongod.conf
關閉 mongod
#mongod -f /etc/mongod.conf --shutdown
執行config server
#mongod -f /etc/mongod-configserv.conf
關閉config server
#mongod -f /etc/mongod-configserv.conf
--shutdown
執行 mongos
#mongos -f /etc/mongod-routingserv.conf
關閉 mongos instance
#killall mongos
導入資料表
#mongoimport --port port_number --db database_name --collection collection_name [--drop] --file file_name
(使用--drop的話,如果資料庫中有名稱相同的collection,會先將舊的collection刪除,在導入新的collection)
(導入CSV指定有點不同,可以去查閱官方文件)
陸、Q&A
問題一:
執行sh.addShard()時出現類似的錯誤
{ "ok" : 0, "errmsg" : "in seed list rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019, host 192.168.1.1:27017 does not belong to replica set rs0; found { hosts: [ \"com6:27017\", \"192.168.1.1:27018\", \"192.168.1.1:27019\" ], setName: \"rs0\", setVersion: 3, ismaster: true, secondary: false, primary: \"com6:27017\", me: \"com6:27017\", electionId: ObjectId('7fffffff0000000000000001'), maxBsonObjectSize: 16777216, maxMessageSizeBytes: 48000000, maxWriteBatchSize: 1000, localTime: new Date(1466274842539), maxWireVersion: 4, minWireVersion: 0, ok: 1.0 }", "code" : 96}
解決辦法:修改rs0的hostname
1. 進入rs0的Primary並輸入rs.status(),檢查"members"的"name"
{ "_id" : 0, "name" : "com6:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 103335, "optime" : { "ts" : Timestamp(1466175445, 12359), "t" : NumberLong(1) }, "optimeDate" : ISODate("2016-06-17T14:57:25Z"), "electionTime" : Timestamp(1466171888, 2), "electionDate" : ISODate("2016-06-17T13:58:08Z"), "configVersion" : 3, "self" : true }如果是像這樣"name":"com6:27017",就要用rs.reconfig()修改"name"
2. 執行以下指令修改"name"
rs0:PRIMARY> cfg=rs.conf()
rs0:PRIMARY> cfg.members[0].host="192.168.1.1:27017"
rs0:PRIMARY> rs.reconfig(cfg)
此時會回傳{ "ok" : 1 }表示修改成功,可以輸入rs.status()檢查成果
此時sh.addShard()應該就可以正常執行
問題二:執行sh.addShard()時出現類似的錯誤
解決辦法一:檢查防火牆設定解決辦法二:在mongos所在的電腦中的/etc/hosts
例如
192.168.1.1 com6
192.168.1.2 com7
192.168.1.3 com8
問題三:執行rs.initiate()時出現以下錯誤
解決辦法:輸入以下指令{
"info2" : "no configuration explicitly specified -- making one",
"me" : "0.0.0.0:27017",
"errmsg" : "couldn't initiate : can't find self in the replset config",
"ok" : 0
}
>cfg = {"_id" : "rs0","members" : [{"_id" : 0,"host" : "192.168.1.1:27017"}]}
(Primary的資料)
>rs.initiate(cfg)
柒、免費資料集
1. https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json
2. http://jsonstudio.com/wp-content/uploads/2014/02/companies.zip
(14.8M compressed)
3. http://jsonstudio.com/wp-content/uploads/2014/02/stocks.zip
(1.6M compressed)
4. http://jsonstudio.com/wp-content/uploads/2014/02/enron.zip
(3.9M compressed)
5. http://jsonstudio.com/wp-content/uploads/2014/02/zips.zip
(656K compressed).
6. http://jsonstudio.com/wp-content/uploads/2014/02/world_bank.zip
(436K compressed)
沒有留言:
張貼留言