群組文章
[Linux] mongodb 初步--1/3 安裝及基本操作[Linux] mongodb 初步--3/3 權限和幫助
使用mongodb的一些大小事:關於叢集。
個人認為一個好的資料庫叢集應該有下面的特性:
- 易於安裝及設定
- 單一伺服器死機不影響運作
- 空間不足時可以平行擴展,不用重裝
- 叢集中單元數增加不會影響效能太多,尤其是搜尋時
- 易於維護及查錯,或有管理工具
因此,在使用mongo的叢集時,一定要先把他給搞懂,以下的文字都是用我的話寫的,如有疑問或錯誤歡迎討論。
一、名詞解釋
1. replica set 複本組(我給他的中文名)
複本組是非同步的「主要/隨從資料庫」型式,再加上自動的失敗復原功能,簡單的來說,就是「主從式」的架構。
- 一個複本組由2個及以上的結點組成,這裡的結點指的是一個mongod,有配置一個實體的目錄空間。
- 同一個複本組裡面的結點所存的內容會相同。
- 這個複本組會自動的選出一個主要的結點,我們不必指定誰是主要的。
- 主要的結點可以讀寫,隨從結點只能讀
- mongos(也就是route角色的mongod)自動會去找主要結點來寫入,對於sharding亦同。
2. sharding 切片
sharding是指一個「切片的方法」,這個方法可使資料庫藉由自動分割的方式平行擴展。叢集資料庫中每一個單元叫shard(一個切片),叢集資料庫可由數個切片組成;每一個切片中可包含一個複本組或是一個結點所組成。
3. Sharded Cluster 切片的叢集
將許多的分散的資料庫程式集合在一起,看起來就像只有一個資料庫的方法叫叢集。mongodb採用切片的方法來叢集,所以叫切片的叢集(Sharded Cluster)。
這個方法,就像是政府目前推行的「單一窗口」,讓洽公的民眾不必打電話轉來轉去找不到承辦單位,由統一的窗口單位幫你轉到能幫你處理事情的單位。
4. oplog(operations log) 操作記錄
不由分說,這個東西就是管理叢集資料庫的操作,它其實是一個包裝過的資料表(capped collection),裡面記錄所有修改的操作以供所有的複本組同步使用,每個複本組中的結點都會複製一份oplog來維持同步,Linux中預設會用磁碟空間的5%,如果資料庫拿來存檔案的話,空間不宜太小以策安全。
二、規畫
這是我的規畫
規畫的考量
- 可容許最多二台伺服器同時故障而不會影響資料的完整性及可用性。
- 可平行擴展以支持未來資料量大增的需求(因為要來存檔案,使用量增加很快)
- 如果只有三台伺服器可用,可採用[3]的規畫方式
- 接入點使用預設的27017埠,省去修改程式的麻煩。
三、設定
因為只有三台伺服器,所以暫時只設定rs1和rs2這兩個複本組,爾後有增加伺服器時,再增加設定rs3, rs4.....
1. 建立資料庫目錄
[SERVER1]
# cd /var/lib/mongo/
# mkdir rs1data
# mkdir config
# chown mongod:mongod rs1data
# chown mongod:mongod config
[SERVER2], [SERVER3]
# cd /var/lib/mongo/
# mkdir rs1data
# mkdir rs2data
# mkdir config
# chown mongod:mongod rs1data
# chown mongod:mongod rs2data
# chown mongod:mongod config
2. 建立複本組
將oplog設為2G
[SERVER1]
# mongod --shardsvr --replSet rs1 --port 28001 --dbpath /var/lib/mongo/rs1data --oplogSize 2000 --logpath /var/lib/mongo/rs1.log --logappend --fork
[SERVER2], [SERVER3]
# mongod --shardsvr --replSet rs1 --port 28001 --dbpath /var/lib/mongo/rs1data --oplogSize 2000 --logpath /var/lib/mongo/rs1.log --logappend --fork
# mongod --shardsvr --replSet rs2 --port 28002 --dbpath /var/lib/mongo/rs2data --oplogSize 2000 --logpath /var/lib/mongo/rs2.log --logappend --fork
3. 初始化複本組
分別連到複本組rs1及rs2其中一個node:
[rs1]
# mongo 163.17.38.80:28001
MongoDB shell version: 2.2.2
connecting to: 163.17.38.80:28001/test
> cfg={ _id : 'rs1', members : [ {_id:0, host: '163.17.38.80:28001'},
{_id:1, host: '163.17.38.81:28001'}, {_id:2, host: '163.17.38.84:28001'}, ] }
> rs.initiate(cfg);
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
[rs2]
# mongo 163.17.38.81:28002
MongoDB shell version: 2.2.2
connecting to: 163.17.38.80:28001/test
> cfg={ _id : 'rs2', members : [ {_id:0, host: '163.17.38.81:28002'},
{_id:1, host: '163.17.38.84:28002'}, ] }
> rs.initiate(cfg);
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
查看rs狀態:
> rs.status();
看誰是主要master
> db.isMaster()
更多指令
> rs.help();
4. 設置config server
[SERVER1], [SERVER2], [SERVER3]
# mongod --configsvr --port 28000 --dbpath /var/lib/mongo/config --logpath /var/lib/mongo/config.log --logappend --fork
到此為止config server 和複本組還沒有任可關聯,換句話說,複本組還不知道config server的存在。所以,接下來就是要配置route server,讓他和config server產生關聯。
5. 設置route server(mongos)
這裡我採用32MB(預設是64MB)作為chunksize,數字越大越不容易平均分散,數字越小效能會降低。
[SERVER1], [SERVER2], [SERVER3]
# mongos --configdb 163.17.38.80:28000,163.17.38.81:28000,163.17.38.84:28000 --port 27017 --chunkSize 32 --logpath /var/lib/mongo/mongos.log --logappend --fork
6. 組態 sharded cluster
最後要做的事,就是讓mongos知道有那些rs可以用,並把每個rs編成shard
連到任一台的mongos
# mongo 163.17.38.80:27017
mongos> use admin; switched to db admin mongos> db.runCommand( {addshard: "rs1/163.17.38.80:28001,163.17.38.81:28001,163.17.38.84:28001", name: "sh1", maxsize:50}); { "shardAdded" : "sh1", "ok" : 1 } mongos> db.runCommand( {addshard: "rs2/163.17.38.81:28002,163.17.38.84:28002", name: "sh2", maxsize:50}); { "shardAdded" : "sh2", "ok" : 1 } // 觀察我的切片 mongos> db.runCommand( { listshards : 1 } ) { "shards" : [ { "_id" : "sh2", "host" : "rs2/163.17.38.81:28002,163.17.38.84:28002" }, { "_id" : "sh1", "host" : "rs1/163.17.38.80:28001,163.17.38.81:28001,163.17.38.84:28001" } ], "ok" : 1 } // 將資料庫拿來切片,執行這個指令後,該資料庫不同collection會被放在不同切片,但collection本身不再被切片 mongos> db.runCommand( { enablesharding: "<dbname>" } ); ex: mongos> db.runCommand( { enablesharding : "test" } ); { "ok" : 1 }
7. 將collection 也切片
如果只有資料庫切片,遇到比較大的collection,就會有平均的問題出現。記得 enablesharding 的指令要先下後才執行這個指令。
它的寫法是
> db.runCommand({ shardCollection: "<db>.<collection>", key: <shardkey> });
這裡的 key 是指collection中再被切的依據方法
ex:
mongos> use test
mongos> db.createCollection("c1");
{ "ok" : 1 }
備註
1. 要刪除一個執行中的 mongod # mongod --port 28001 --dbpath /var/lib/mongo/rs1data --shutdown
2. 如果在初始化複本組出現這樣的錯誤,請確定你的mongod有沒有正常啟動,或是被防火牆擋住了
> rs.initiate(cfg);
{ "errmsg" : "couldn't initiate : need all members up to initiate, not ok : 163.17.38.81:28001", "ok" : 0 }
3. 查看rs的狀況
> db._adminCommand("replSetGetStatus")
如果出現 "errmsg" : "still initializing",就要去檢查錯誤的log,看看你的防火牆是不擋住了。
4. 查看切片狀態,有shards和databases
> db.printShardingStatus();
--- Sharding Status ---
sharding version: { "_id" : 1, "version" : 3 }
shards:
{ "_id" : "sh1", "host" : "rs1/163.17.38.80:28001,163.17.38.81:28001,163.17.38.84:28001" }
{ "_id" : "sh2", "host" : "rs2/163.17.38.81:28002,163.17.38.84:28002" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : false, "primary" : "sh1" }
感謝
台中市網路中心陳瑩光提的需求
[3] 這個文章對我的幫助最大,感謝阿里巴巴技術小組無私的提供方法
參考資料
[1] Mongodb http://www.mongodb.org/display/DOCS/Replica+Sets
[2] Replication http://www.mongodb.org/display/DOCS/Replication
[3] 配置mongodb分片群集 http://www.taobaodba.com/html/525_525.html
[4] http://www.elmerzhang.com/2011/03/mongodb-auto-sharding-introduction/
[5] Mongo DB Sharding 心得筆記 (一) 有各單元的解釋和平衡的說明 http://leehom59.blogspot.tw/2011/11/mongo-db-sharding.html
原文 2012-12-10 12:23:09