天天看點

mongodb搭建叢集

如果想配置2個mongos,1個config,多個mongod也可以 

mongos比較耗cpu,mongod比較耗記憶體,但其實負載都很低。 

機器1:1個mongos和1個config 

[root@iz28s3djhumz ~]# ps -ef|grep mongo 

root     13617     1  0 17:12 ?        00:00:07 mongod --dbpath=/mongo_config --port 27030 --fork --logpath=/mongo_config/mongo_config.log 

root     13654     1  0 17:19 ?        00:00:01 mongos --port 27031 --configdb=42.96.130.106:27030 --fork --logpath=/mongos/mongos.log 

機器2:1個mongos和1個mongod 

[root@iz28b2hr3cxz /]# ps -ef|grep mongo 

root      9693     1  0 17:15 ?        00:00:05 mongod --dbpath=/mongo2 --port 27032 --fork --logpath=/mongo2/mongo2.log 

root      9704     1  0 17:16 ?        00:00:02 mongos --port 27033 --configdb=42.96.130.106:27030 --fork --logpath=/mongos2/mongos.log 

機器3-n:都是mongod 

root     29486     1  0 17:17 ?        00:00:05 mongod --dbpath=/mongo --port 27036 --fork --logpath=/mongo/mongo5.log 

使用指令: 

[root@iz28s3djhumz ~]# mongo 42.96.130.106:27031/admin 

[root@iz28b2hr3cxz /]# mongo 121.42.169.214:27033/admin 

一邊操作,另一邊可以同步看到結果,是以就相當于一個副本。 

以上的配置,當資料量達到1300萬的時候,mongodb的插入變慢,約為100w/h   之前可以達到120-130w/h 

現在考慮要做負載均衡和修改chunk值來減少資料的遷移 

開始進行叢集搭建 

--- 

1、了解概念 

  mongos:首先我們要了解”片鍵“的概念,也就是說拆分集合的依據是什麼?按照什麼鍵值進行拆分集合....好了,mongos就是一個路由伺服器,它會根據管理者設定的“片鍵”将資料分攤到自己管理的mongod叢集,資料和片的對應關系以及相應的配置資訊儲存在"config伺服器"上。 

  mongod:一個普通的資料庫執行個體,如果不分片的話,我們會直接連上mongod。 

首先我們準備4個mongodb程式,直接在12.104,12.107兩條機器上部署,可以做多個檔案夾的形式。 

2、開啟config伺服器 

 先前也說了,mongos要把mongod之間的配置放到config伺服器裡面,理所當然首先開啟它,我這裡就建立27018端口。 

mongod --dbpath=/mongo --port 27018 

config 

192.168.12.107 /mongo    --端口27018 

3、開啟mongos伺服器 

 這裡要注意的是我們開啟的是mongos,不是mongod,同時指定下config伺服器 

mongod --dbpath=/mongos  --port=27020  --configdb=192.168.12.107:27018 

mongos 

192.168.12.107 /mongos   --端口27020 

[root@viptest2 /]# mongos --port 27020 --configdb=127.0.0.1:27018  --不能指定本地localhost或者127.0.0.1,要使用ip 

[root@viptest2 /]# mongos --port 27020 --configdb=192.168.12.107:27018 

4、啟動mongod伺服器 

  對分片來說,也就是要添加片了,端口為:27017,27019。 

[root@testvip1 /]# mkdir mongo1 

[root@testvip1 /]# mkdir mongo2 

[root@testvip1 /]# mongod --dbpath=/mongo1  --port 27017 

再開一個視窗 

[root@testvip1 /]# mongod --dbpath=/mongo2  --port 27019 

5、服務配置 

 <1> 先前圖中也可以看到,我們client直接跟mongos打交道,也就說明我們要連接配接mongos伺服器,然後将27017,27019的mongod交給mongos,添加分片也就是addshard()。 

  這裡要注意的是,在addshard中,我們也可以添加副本集,這樣能達到更高的穩定性。 

在12.107 mongos上配置分片資訊 

[root@viptest2 ~]# mongo 192.168.12.107:27020/admin 

mongodb shell version: 2.4.6 

connecting to: 192.168.12.107:27020/admin 

welcome to the mongodb shell. 

for interactive help, type "help". 

for more comprehensive documentation, see 

http://docs.mongodb.org/ 

questions? try the support group 

http://groups.google.com/group/mongodb-user 

addshard 遇到的錯誤 

db.runcommand({addshard:”192.168.12.104:27017″}) 

“ok” : 0, 

“errmsg”: “can’t use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual ips host: 192.168.12.104:27017 islocalhost:0″ 

遇到這樣的錯誤是由于某些服務啟動在localhost 位址。 

經過檢查發現route 啟動時,讀取config 服務是讀取的localhost 位址: 

将localhost 修改為ip 位址,問題解決。 

重新進入: 

mongos> 

mongos> db.runcommand({addshard:"192.168.12.104:27019",allowlocal:true }) 

當路由程序和分片在同一台機器上要指定allowlocal為true,因為mongodb盡量避免錯誤的配置,将叢集配置在本地,是以這個配置指明目前僅僅是用于開發。 

因為路由和分片不在同一台機器上,是以不需要執行true,如下添加分片成功 

mongos> db.runcommand({"addshard":"192.168.12.104:27017"}); 

{ "shardadded" : "shard0000", "ok" : 1 } 

mongos> db.runcommand({"addshard":"192.168.12.104:27019"}); 

{ "shardadded" : "shard0001", "ok" : 1 } 

<2>mongos不知道該如何切分資料,也就是我們先前所說的片鍵,在mongodb中設定片鍵要做兩步 

  ①:開啟資料庫分片功能,指令很簡單 enablesharding(),這裡我就開啟test資料庫。 

  ②:指定集合中分片的片鍵,這裡我就指定為person.name字段。 

mongos> show collections;  --檢視表 

mongos> db.runcommand({"drop":"t1"}) --删除表  ---db.t1.drop()一樣的效果 

"nindexeswas" : 1, 

"msg" : "indexes dropped for collection", 

"ns" : "testdb.t1", 

"ok" : 1 

mongos> show dbs;  --檢視資料庫 

admin (empty) 

config 0.1875gb 

mongos> use testdb  --建立資料庫,必須做一些操作,如果是建的空庫,就會自動被删除 

switched to db testdb 

mongos> db.usr.insert({"name":"tom"}); --建立表 

mongos> show collections; 

system.indexes 

usr 

mongos> db.usr.find();   --查找表 

{ "_id" : objectid("541a4f38156a058cc29cce8e"), "name" : "tom" } 

mongos> db.usr.insert({"name":"tom","id":1,"address":"china","phone":"15926492390","sex":"m"})--再插入一條 

mongos> db.usr.find();  --結果顯示兩條 

{ "_id" : objectid("541a4fcd156a058cc29cce8f"), "name" : "tom", "id" : 1, "address" : "china", "phone" : "15926492390", "sex" : "m" } 

mongos> db.runcommand({"enablesharding":"testdb"}) 

{ "ok" : 0, "errmsg" : "access denied - use admin db" } --要使用admin資料庫進行配置 

mongos> use admin 

switched to db admin 

mongos> db.runcommand({"enablesharding":"testdb"}) --切換到admin果然配置成功 

{ "ok" : 1 } 

表進行分片 

mongos> db.runcommand({"shardcollection":"testdb.usr","key":{"id":1}}) 

"proposedkey" : { 

"id" : 1 

}, 

"curindexes" : [ 

"v" : 1, 

"key" : { 

"_id" : 1 

"ns" : "testdb.usr", 

"name" : "_id_" 

], 

"ok" : 0, 

"errmsg" : "please create an index that starts with the shard key before sharding." --提示需要先建索引 

原來判斷分支是查找是否有可用的索引存在,當無可用的索引,并且表不為空時,就會出現這個錯誤資訊。 

好了找到根源了,現在解決問題:在分片key上個建立索引 

use testdb 

db.usr.ensureindex({"id":1}) 

然後對表進行分片 

"errmsg" : "found missing value in key { id: null } for doc: { _id: objectid('541a4f38156a058cc29cce8e'), name: \"tom\" }"--最開始插入的一條有問題,沒有id這個字段 

修改這條記錄: 

mongos> db.usr.update({"name":"tom"},{"name":"tina","id":2,"address":"us","phone":"18707551657","sex":"f"}) 

mongos> db.usr.find(); 

{ "_id" : objectid("541a4f38156a058cc29cce8e"), "name" : "tina", "id" : 2, "address" : "us", "phone" : "18707551657", "sex" : "f" } 

結果顯示: 

mongos> db.runcommand({"shardcollection":"testdb.usr","key":{"id":1}})  

{ "collectionsharded" : "testdb.usr", "ok" : 1 }   --建立成功,以id為分片的主鍵 

6、 檢視效果 

  好了,至此我們的分片操作全部結束,接下來我們通過mongos向mongodb插入多條記錄,然後通過printshardingstatus指令檢視mongodb的資料分片情況。 

  這裡主要看三點資訊: 

  ① shards: 我們清楚的看到已經别分為兩個片了,shard0000和shard0001。 

  ② databases: 這裡有個partitioned字段表示是否分區,這裡清楚的看到已經分區。 

  ③ chunks: 集合 

mongos> use testdb 

mongos> db.printshardingstatus() 

--- sharding status --- 

  sharding version: { 

"_id" : 1, 

"version" : 3, 

"mincompatibleversion" : 3, 

"currentversion" : 4, 

"clusterid" : objectid("541a47a9124d847f09e99204") 

  shards: 

{  "_id" : "shard0000",  "host" : "192.168.12.104:27017" } 

{  "_id" : "shard0001",  "host" : "192.168.12.104:27019" } 

  databases: 

{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" } 

{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" } 

testdb.usr 

shard key: { "id" : 1 } 

chunks: 

shard0000 1 

{ "id" : { "$minkey" : 1 } } -->> { "id" : { "$maxkey" : 1 } } on : shard0000 timestamp(1, 0) 

--插入1000條資料 

mongos> for (var i=0;i<1000;i++){db.usr.insert({"name":"tina"+i,"id":3+i,"address":"china","phone":15926492390+i,"sex":"m"})} 

--在路由mongo上連接配接單個分片 

[root@testvip1 ~]# mongo 192.168.12.104:27017   

connecting to: 192.168.12.104:27017/test 

> use testdb 

> show collections 

> db.usr.find() 

{ "_id" : objectid("541a5455156a058cc29cce91"), "id" : 3, "name" : "tina0", "address" : "china", "phone" : 15926492390, "sex" : "m" } 

type "it" for more 

> db.usr.status() 

thu sep 18 14:54:19.410 typeerror: property 'status' of object testdb.usr is not a function 

> db.usr.status 

testdb.usr.status 

thu sep 18 14:54:31.494 typeerror: property 'status' of object testdb.usr is not a function 

> db.usr.count()    --以id做key,結果全部分到一個分片上了。 

35407 

-------------------