天天看點

公司MongoDB 實施方案

綠岸網絡MongoDB

                                                                                             ---何旭東

目錄

綠岸網絡MongoDB. 1

場景介紹... 1

機器功能:... 2

主機名... 2

邏輯圖... 3

primary secondary. 4

模型選擇... 4

啟動... 5

第一台... 5

第二台... 5

第三台... 5

配置... 5

第二台... 6

第三台... 7

啟動路由... 8

分片... 8

添加分片... 9

配置結果... 9

檢視目前主庫... 11

調整從庫可讀... 12

模拟故障... 13

主機點當機... 13

從節點自動提升主節點... 13

主機點恢複... 14

問題... 15

臨時調整,不生效... 15

程式實作可讀... 17

場景介紹

MongoDB 3.0其實是2.8,上個版本是2.6.2.8有極大的增加,用2.8有點委屈,在MongoDB市場部主導命名3.0. 增加了高性能,可伸縮的存儲引擎wiredtiger.性能有了極大的提升,尤其在寫操作對硬體資源的使用率。

mongodb最初版本一直到2.6都隻支援一種基于記憶體映射技術的存儲引擎即mmap。mongodb 3.0實作對支援集合級鎖的存儲引擎mmap和支援壓縮和文檔級鎖的存儲引擎wiredtiger的支援。

MongoDB官方同步釋出了一份YCSB測試報告。

且官方下載下傳資源,确實了沒有2.8。以下為官方下載下傳位址

https://www.mongodb.org/downloads?_ga=1.220177757.596614690.1431100647#development

機器功能:

機器 角色名稱 端口 功能
mongod01 28017 'shard1'   PRIMARY
mongoc01 20000 配置節點
mongos01 28885 路由節點
41000 啟動路由  生成此端口
mongod02 'shard1'   SECONDARY
mongoc02
mongos02
mongod03 'shard1'   arbiter
mongoc03

Shardingoptions:

  --configdb arg        1 or 3 comma separated config servers

路由節點隻能配置1 或者 3 個!

主機名

192.168.200.87   mongohost1

192.168.200.90   mongohost2

192.168.200.88   mongohost3

192.168.200.87   mongo01

192.168.200.87   mongodb01

192.168.200.87   mongos01

192.168.200.90   mongo02

192.168.200.90   mongodb02

192.168.200.90   mongos02

192.168.200.88   mongo03

192.168.200.88   mongodb03

邏輯圖

公司MongoDB 實施方案

primary secondary

公司MongoDB 實施方案

模型選擇

CAP定理(Consistency ,Availability和Partition Tolerance)

–Consistency(一緻性):資料一緻更新,所有資料變動都是同步的

–Availability(可用性):好的響應性能

–PartitionTolerance(分區容錯性):資料可靠性

–分布式系統三選二

官方CP模型

CP

–ReplicaSet,設定寫入節點數w=ReplicaSet資料節點數,查詢開啟SlaveOk

AP

–ReplicaSet,預設設定w=1,查詢開啟slaveOk

CA

–ReplicaSet,預設設定w=1,查詢不開啟slaveOk

啟動

第一台

mongod -f /etc/shard11.conf

mongod -f /etc/config1.conf

mongos -f /etc/mongos1.conf

第二台

mongod -f /etc/shard12.conf

mongod -f /etc/config2.conf

mongos -f /etc/mongos2.conf

第三台

mongod -f /etc/shard13.conf

mongod -f /etc/config3.conf

配置

mkdir /usr/local/mongodb/shard11/ -p

mkdir /usr/local/mongodb/config/

mkdir /usr/local/mongodb/logs/

cat > /etc/shard11.conf <<EOF

shardsvr=true

port=28017

dbpath = /usr/local/mongodb/shard11/

logpath = /usr/local/mongodb/logs/shard11.log

logappend=true

fork=true

nojournal=true

rest=true

replSet=shard1

oplogSize=2048

EOF

cat > /etc/config1.conf <<EOF

configsvr=true

port=20000

dbpath = /usr/local/mongodb/config/

logpath =/usr/local/mongodb/logs/config1.log

cat > /etc/mongos1.conf <<EOF

configdb=mongodb01:20000,mongodb02:20000,mongodb03:20000

chunkSize=100

port=28885

logpath =/usr/local/mongodb/logs/mongos1.log

mkdir /usr/local/mongodb/shard12/ -p

cat > /etc/shard12.conf <<EOF

dbpath = /usr/local/mongodb/shard12/

logpath =/usr/local/mongodb/logs/shard12.log

logpath =/usr/local/mongodb/logs/config2.log

cat > /etc/mongos2.conf <<EOF

configdb = mongodb01:20000,mongodb02:20000,mongodb03:20000

logpath =/usr/local/mongodb/logs/mongos2.log

mkdir /usr/local/mongodb/shard13/ -p

mkdir  /usr/local/mongodb/logs/

cat > /etc/shard13.conf <<EOF

dbpath = /usr/local/mongodb/shard13/

logpath = /usr/local/mongodb/logs/shard13.log

cat > /etc/config3.conf <<EOF

logpath = /usr/local/mongodb/logs/config3.log

啟動路由

參考

mongos --configdbmongohost3:20000,mongohost2:20000,mongohost1:20000 --port 41000 --chunkSize 100--logpath /usr/local/mongodb/logs/mongos.log --logappend --fork

綠岸配置

mongos --configdb mongodb01:20000,mongodb02:20000,mongodb03:20000--port 41000 --chunkSize 100 --logpath /usr/local/mongodb/logs/mongos.log--logappend --fork

分片

以下為參考配置

mongo mongohost1:28017/admin

config = {_id:'shard1', members: [{_id: 0,host: 'mongohost1:28017'},{ "_id" : 1,"host":"mongohost2:28017",},{_id:2, host: 'mongohost3:28017', arbiterOnly : true}]};

rs.initiate(config);

以下為綠岸配置

mongo mongo01:28017/admin

config = {_id:'shard1', members: [{_id: 0,host: 'mongo01:28017'},{ "_id" : 1,"host":" mongo02:28017",},{_id:2, host: ' mongo03:28017', arbiterOnly : true}]};

添加分片

mongo mongohost1:28885/admin

db.runCommand({"addshard" :"shard1/mongohost1:28017,mongohost2:28017"})

mongo mongos01:28885/admin

db.runCommand({"addshard" :"shard1/mongo01:28017,mongo02:28017"})

配置結果

[root@mongohost1 mongodb]# mongomongohost1:28885/admin

MongoDB shell version: 2.6.10

connecting to: mongohost1:28885/admin

mongos> db.printShardingStatus();

--- Sharding Status ---

 sharding version: {

       "_id" : 1,

       "version" : 4,

       "minCompatibleVersion" : 4,

       "currentVersion" : 5,

       "clusterId" : ObjectId("55adedc8c5488912b58e20aa")

}

 shards:

       {  "_id" :"shard1",  "host" :"shard1/mongohost1:28017,mongohost2:28017" }

 databases:

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

       { "_id" : "shard1", "host" : "shard1/mongohost1:28017,mongohost2:28017"}

mongos> rs.status()

{

       "info" : "mongos",

       "ok" : 0,

       "errmsg" : "replSetGetStatus is not supported throughmongos"

mongos> exit

bye

[root@mongohost1 mongodb]# mongomongohost1:28017/admin

connecting to: mongohost1:28017/admin

Server has startup warnings:

2015-07-21T14:57:14.934+0800 ** WARNING:--rest is specified without --httpinterface,

2015-07-21T14:57:14.934+0800 **          enabling http interface

2015-07-21T14:57:14.939+0800[initandlisten]

2015-07-21T14:57:14.939+0800[initandlisten] ** WARNING: Readahead for /usr/local/mongodb/shard11/ is set to4096KB

2015-07-21T14:57:14.939+0800[initandlisten] **          We suggestsetting it to 256KB (512 sectors) or less

2015-07-21T14:57:14.939+0800[initandlisten] **         http://dochub.mongodb.org/core/readahead

shard1:PRIMARY> rs.status();

       "set" : "shard1",

       "date" : ISODate("2015-07-21T07:13:20Z"),

       "myState" : 1,

       "members" : [

                {

                        "_id" : 0,

                        "name" :"mongohost1:28017",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" :"PRIMARY",

                        "uptime" :966,

                        "optime" :Timestamp(1437462480, 1),

                        "optimeDate": ISODate("2015-07-21T07:08:00Z"),

                       "electionTime" : Timestamp(1437462489, 1),

                       "electionDate" : ISODate("2015-07-21T07:08:09Z"),

                        "self" : true

                },

                        "_id" : 1,

                        "name" :"mongohost2:28017",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" :"SECONDARY",

                        "uptime" :319,

                        "optime" :Timestamp(1437462480, 1),

                       "lastHeartbeat" : ISODate("2015-07-21T07:13:19Z"),

                       "lastHeartbeatRecv" : ISODate("2015-07-21T07:13:18Z"),

                        "pingMs" : 0,

                        "syncingTo" :"mongohost1:28017"

                        "_id" : 2,

                        "name" :"mongohost3:28017",

                       "health": 1,

                        "state" : 7,

                        "stateStr" :"ARBITER",

                        "lastHeartbeatRecv": ISODate("2015-07-21T07:13:18Z"),

                        "pingMs" : 0

                }

       ],

       "ok" : 1

shard1:PRIMARY>

檢視目前主庫

shard1:PRIMARY> rs.isMaster();

       "setName" : "shard1",

       "setVersion" : 1,

       "ismaster" : true,

       "secondary" : false,

       "hosts" : [

                "mongohost1:28017",

                "mongohost2:28017"

       "arbiters" : [

                "mongohost3:28017"

       "primary" : "mongohost1:28017",

       "me" : "mongohost1:28017",

       "electionId" : ObjectId("55adefda41c78564aaa0ffd8"),

       "maxBsonObjectSize" : 16777216,

       "maxMessageSizeBytes" : 48000000,

       "maxWriteBatchSize" : 1000,

       "localTime" : ISODate("2015-07-21T07:21:14.600Z"),

       "maxWireVersion" : 2,

       "minWireVersion" : 0,

調整從庫可讀

passive     ----節點執行以下内容

testSet:PRIMARY> show dbs;

admin (empty)

local 2.077GB

testSet:PRIMARY> use testdb;

switched to db testdb

testSet:PRIMARY>db.document01.insert({"name":"hxd","sex":"N","age":"22"});

WriteResult({ "nInserted" : 1 })

testSet:PRIMARY> show tables;

document01

system.indexes

testSet:PRIMARY> db.document01.find();

{ "_id" :ObjectId("55a71118442e12ca0d28b50a"), "name" :"hxd", "sex" : "N", "age" :"22" }

testSet:PRIMARY>

standard    ----節點執行以下内容

testSet:SECONDARY> show dbs;

admin  (empty)

local  2.077GB

testdb 0.078GB

testSet:SECONDARY> use testdb

testSet:SECONDARY> show tables;

2015-07-16T10:05:22.978+0800 error: {"$err" : "not master and slaveOk=false", "code" :13435 } at src/mongo/shell/query.js:131

testSet:SECONDARY> rs.slaveOk();

testSet:SECONDARY> db.document01.find();

testSet:SECONDARY>

模拟故障

主機點當機

[root@mongohost1 mongodb]# ps aux | grepshard11.conf

root     2142  0.4  5.6 2888808 56768 ?       Sl  14:57   0:07 mongod -f/etc/shard11.conf

root     5191  0.0  0.0 112640  972 pts/0    S+   15:25  0:00 grep --color=auto shard11.conf

[root@mongohost1 mongodb]# kill -2 2142

從節點自動提升主節點

shard1:SECONDARY> db.document01.find();

{ "_id" :ObjectId("55adf36ae512c815a6569440"), "name" :"hxd", "sex" : "N", "age" :"22" }

shard1:SECONDARY> rs.status()

       "date" : ISODate("2015-07-21T07:25:47Z"),

                        "health" : 0,

                        "state" : 8,

                        "stateStr" : "(not reachable/healthy)",

                        "uptime" : 0,

                        "optime" :Timestamp(1437463402, 1),

                        "optimeDate": ISODate("2015-07-21T07:23:22Z"),

                       "lastHeartbeat" : ISODate("2015-07-21T07:25:47Z"),

                       "lastHeartbeatRecv" : ISODate("2015-07-21T07:25:39Z"),

                        "stateStr" : "PRIMARY",

                        "uptime" :1683,

                        "electionTime" :Timestamp(1437463543, 1),

                       "electionDate" : ISODate("2015-07-21T07:25:43Z"),

                        "uptime" :1063,

                       "lastHeartbeatRecv" :ISODate("2015-07-21T07:25:46Z"),

主機點恢複

主節點當機狀态:

"stateStr" : "(notreachable/healthy)",

恢複主節點後:

"stateStr" :"SECONDARY",

問題

問題:

降級的SECONDARY 為不可讀模式。需手動調整。

在已更新成為:mongohost2 PRIMARY 節點插入資料。

shard1:PRIMARY> show dbs;

shard1:PRIMARY> use testdb;

shard1:PRIMARY>db.document01.insert({"name":"lazy","sex":"N","age":"52"});

shard1:PRIMARY> show tables;

shard1:PRIMARY> db.document01.find();

{ "_id" : ObjectId("55adf36ae512c815a6569440"),"name" : "hxd", "sex" : "N","age" : "22" }

{ "_id" :ObjectId("55adf6ddc036dfbdc18191cc"), "name" :"lazy", "sex" : "N", "age" :"52" }

shard1:PRIMARY> exit

[root@mongohost2 mongodb]#

在已降級成為:mongohost1 SECONDARY 節點檢視資料

shard1:SECONDARY> rs.slaveOk();

shard1:SECONDARY> exit

[root@mongohost1 mongodb]#

臨時調整,不生效

手動配置slaveOk ,為臨時。exit退出後,将失去讀取權限,問題 求解決。

以下為測試案例:

shard1:SECONDARY> show dbs;

admin   (empty)

local   2.077GB

testdb  0.078GB

shard1:SECONDARY> use testdb

switched to db testdb

shard1:SECONDARY> show tables;

2015-07-21T15:52:12.008+0800 error: { "$err" : "not master and slaveOk=false", "code" : 13435 } at src/mongo/shell/query.js:131

shard1:SECONDARY> db.document01.find();

error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

shard1:SECONDARY> rs.slaveOk();

{ "_id" : ObjectId("55adf36ae512c815a6569440"), "name" : "hxd", "sex" : "N", "age" : "22" }

{ "_id" : ObjectId("55adf6ddc036dfbdc18191cc"), "name" : "lazy", "sex" : "N", "age" : "52" }

shard1:SECONDARY> exit

[root@mongohost1 mongodb]# mongo mongohost1:28017/admin     再次登入

MongoDB shell version: 2.6.10

connecting to: mongohost1:28017/admin

Server has startup warnings: 

2015-07-21T15:28:05.172+0800 ** WARNING: --rest is specified without --httpinterface,

2015-07-21T15:28:05.172+0800 **          enabling http interface

2015-07-21T15:28:05.176+0800 [initandlisten] 

2015-07-21T15:28:05.176+0800 [initandlisten] ** WARNING: Readahead for /usr/local/mongodb/shard11/ is set to 4096KB

2015-07-21T15:28:05.176+0800 [initandlisten] **          We suggest setting it to 256KB (512 sectors) or less

2015-07-21T15:28:05.176+0800 [initandlisten] **          http://dochub.mongodb.org/core/readahead

shard1:SECONDARY>  db.document01.find();

[root@mongohost1 mongodb]# 

北京-何旭東 2015/7/21 15:57:15

以上為mongohost1 ,在首次配置中為:PRIMARY狀态。當mongohost1 資料節點當機後。mongohost2 成為PRIMARY 狀态。

現狀: 想對mongohost1  進行讀取操作,沒有配置生效。

我找一下這個問題的答案,大家也可以想一下。

程式實作可讀

就以上截圖,重點說明了。1   當首次查詢 沒有權限,手從操作後,再次查詢,沒有問題。exit退出後

                                       2  退出後,再次登入查詢,發現又沒有了  權限。 請求。

此次說明了。rs.slave0k();  為臨時生效,退出後 依然沒有查詢權限。

16:08:13

 2015/7/21 16:08:13

的确如此:slaveOk隻對當次的連接配接生效。每次連接配接之後都要判斷一次目前是否master,不是就重新設定,的确有些不太合理了。

看看老師有什麼解決方法

16:08:54

老師-孫玄2015/7/21 16:08:54

如果使用driver,在程式裡可以設定永久開啟slaveok

老師-孫玄2015/7/21 16:09:11

如果使用shell用戶端,的确每次都有設定slaveok

老師-孫玄2015/7/21 16:09:19

不然從庫讀不了

37537-廈門-陳 2015/7/21 16:09:54

MongoDB為什麼要這麼設計呀?

 2015/7/21 16:09:57

也就是使用driver的話,不管是否連master,都設定一次slaveok?

北京-何旭東 2015/7/21 16:10:04

哦。一會咨詢下,我們的這邊的大神。謝謝老師回答

 2015/7/21 16:10:28

這是一種保護機制:防止誤讀取了從庫,以至于讀取到非最新的資料。

實作

PRIMARY 節點 寫入

SECONDARY 節點 讀取

老師-孫 2015/7/21 16:15:51

基于paxos算法

老師-孫 2015/7/21 16:16:25

@北京-何旭東 這點replic set集合支援的

老師-孫 2015/7/21 16:16:30

開啟slaveok就可以

 2015/7/21 16:16:49

但之前程式是直接連接配接的單個節點,原本連接配接的這個節點是主庫,重新選舉後其他節點變成了主庫,此節點變成從庫。那程式在沒有調整設定之前,如何從從庫讀取資料呢?

 2015/7/21 16:17:06

是以,還是經過mongos是最佳的方案。

老師-孫 2015/7/21 16:17:21

對,直接連接配接資料節點,不行的

16:17:30

 2015/7/21 16:17:30

也就是說副本集最好與分片一起,否則,讀寫分離上有些麻煩?

老師-孫 2015/7/21 16:17:31

經過mongos就沒有這個問題了

老師-孫 2015/7/21 16:17:45

不是

老師-孫 2015/7/21 16:18:03

一個replic set 内部是支援讀寫分離的

老師-孫 2015/7/21 16:18:11

和sharding沒有必然關系

繼續閱讀