搭建高可用MongoDB集群(分片)

MongoDB基礎請參考:http://blog.51cto.com/kaliarch/2044423

MongoDB(replica set)請參考:http://blog.51cto.com/kaliarch/2044618

一、概述

1.1 背景

為解決mongodb在replica set每個從節點上面的數據庫均是對數據庫的全量拷貝,從節點壓力在高并發大數據量的場景下存在很大挑戰,同時考慮到后期mongodb集群的在數據壓力巨大時的擴展性,應對海量數據引出了分片機制。

1.2 分片概念

分片是將數據庫進行拆分,將其分散在不同的機器上的過程,無需功能強大的服務器就可以存儲更多的數據,處理更大的負載,在總數據中,將集合切成小塊,將這些塊分散到若干片中,每個片只負載總數據的一部分,通過一個知道數據與片對應關系的組件mongos的路由進程進行操作。

1.3 基礎組件

其利用到了四個組件:mongos,config server,shard,replica set

mongos:數據庫集群請求的入口,所有請求需要經過mongos進行協調,無需在應用層面利用程序來進行路由選擇,mongos其自身是一個請求分發中心,負責將外部的請求分發到對應的shard服務器上,mongos作為統一的請求入口,為防止mongos單節點故障,一般需要對其做HA。

config server:配置服務器,存儲所有數據庫元數據(分片,路由)的配置。mongos本身沒有物理存儲分片服務器和數據路由信息,只是存緩存在內存中來讀取數據,mongos在第一次啟動或后期重啟時候,就會從config server中加載配置信息,如果配置服務器信息發生更新會通知所有的mongos來更新自己的狀態,從而保證準確的請求路由,生產環境中通常也需要多個config server,防止配置文件存在單節點丟失問題。

shard:在傳統意義上來講,如果存在海量數據,單臺服務器存儲1T壓力非常大,無論考慮數據庫的硬盤,網絡IO,又有CPU,內存的瓶頸,如果多臺進行分攤1T的數據,到每臺上就是可估量的較小數據,在mongodb集群只要設置好分片規則,通過mongos操作數據庫,就可以自動把對應的操作請求轉發到對應的后端分片服務器上。

replica set:在總體mongodb集群架構中,對應的分片節點,如果單臺機器下線,對應整個集群的數據就會出現部分缺失,這是不能發生的,因此對于shard節點需要replica set來保證數據的可靠性,生產環境通常為2個副本+1個仲裁。

1.4 架構圖

二、安裝部署

2.1 基礎環境

為了節省服務器,采用多實例配置,三個mongos,三個config server,單個服務器上面運行不通角色的shard(為了后期數據分片均勻,將三臺shard在各個服務器上充當不同的角色。),在一個節點內采用replica set保證高可用,對應主機與端口信息如下:

主機名

IP地址

組件mongos

組件config server

shard

mongodb-1

172.20.6.10

端口:20000

端口:21000

主節點:?? 22001

副本節點:22002

仲裁節點:22003

mongodb-2

172.20.6.11

端口:20000

端口:21000

仲裁節點:22001

主節點:?? 22002

副本節點:22003

mongodb-3

172.20.6.12

端口:20000

端口:21000

副本節點:22001

仲裁節點:22002

主節點:?? 22003

2.2、安裝部署

2.2.1 軟件下載目錄創建

wget?-c?https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.10.tgz

tar?-zxvf?mongodb-linux-x86_64-rhel62-3.4.10.tgz

ln?-sv?mongodb-linux-x86_64-rhel62-3.4.10?mongodb

echo?"PATH=$PAHT:/usr/local/mongodb/bin">/etc/profile.d/mongodb.sh

source?/etc/profile.d/mongodb.sh

2.2.2 創建目錄

分別在mongodb-1/mongodb-2/mongodb-3創建目錄及日志文件

mkdir?-p?/data/mongodb/mongos/{log,conf}

mkdir?-p?/data/mongodb/mongoconf/{data,log,conf}

mkdir?-p?/data/mongodb/shard1/{data,log,conf}

mkdir?-p?/data/mongodb/shard2/{data,log,conf}

mkdir?-p?/data/mongodb/shard3/{data,log,conf}

touch?/data/mongodb/mongos/log/mongos.log

touch?/data/mongodb/mongoconf/log/mongoconf.log

touch?/data/mongodb/shard1/log/shard1.log

touch?/data/mongodb/shard2/log/shard2.log

touch?/data/mongodb/shard3/log/shard3.log

2.2.3 配置config server副本集

在mongodb3.4版本后要求配置服務器也創建為副本集,在此副本集名稱:replconf

在三臺服務器上配置config server副本集配置文件,并啟動服務

cat>/data/mongodb/mongoconf/conf/mongoconf.conf<

logpath=/data/mongodb/mongoconf/log/mongoconf.log????????#定義config?server日志文件

logappend=true

port?=?21000

maxConns?=?1000????????????#鏈接數

journal?=?true????????????#日志開啟

journalCommitInterval?=?200

fork?=?true????????????#后臺執行

syncdelay?=?60

oplogSize?=?1000

configsvr?=?true????????#配置服務器

replSet=replconf????????#config?server配置集replconf

EOF

mongod?-f?/data/mongodb/mongoconf/conf/mongoconf.conf????????#三臺服務器均啟動config?server

任意登錄一臺服務器進行配置服務器副本集初始化

use?admin

config?=?{_id:"replconf",members:[

{_id:0,host:"172.20.6.10:21000"},

{_id:1,host:"172.20.6.11:21000"},

{_id:2,host:"172.20.6.12:21000"},]

}

rs.initiate(config);

查看集群狀態:

replconf:OTHER>?rs.status()

{

"set"?:?"replconf",

"date"?:?ISODate("2017-12-04T07:42:09.054Z"),

"myState"?:?1,

"term"?:?NumberLong(1),

"configsvr"?:?true,

"heartbeatIntervalMillis"?:?NumberLong(2000),

"optimes"?:?{

"lastCommittedOpTime"?:?{

"ts"?:?Timestamp(1512373328,?1),

"t"?:?NumberLong(1)

},

"readConcernMajorityOpTime"?:?{

"ts"?:?Timestamp(1512373328,?1),

"t"?:?NumberLong(1)

},

"appliedOpTime"?:?{

"ts"?:?Timestamp(1512373328,?1),

"t"?:?NumberLong(1)

},

"durableOpTime"?:?{

"ts"?:?Timestamp(1512373328,?1),

"t"?:?NumberLong(1)

}

},

"members"?:?[

{

"_id"?:?0,

"name"?:?"172.20.6.10:21000",

"health"?:?1,

"state"?:?1,

"stateStr"?:?"PRIMARY",

"uptime"?:?221,

"optime"?:?{

"ts"?:?Timestamp(1512373328,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T07:42:08Z"),

"infoMessage"?:?"could?not?find?member?to?sync?from",

"electionTime"?:?Timestamp(1512373296,?1),

"electionDate"?:?ISODate("2017-12-04T07:41:36Z"),

"configVersion"?:?1,

"self"?:?true

},

{

"_id"?:?1,

"name"?:?"172.20.6.11:21000",

"health"?:?1,

"state"?:?2,

"stateStr"?:?"SECONDARY",

"uptime"?:?42,

"optime"?:?{

"ts"?:?Timestamp(1512373318,?1),

"t"?:?NumberLong(1)

},

"optimeDurable"?:?{

"ts"?:?Timestamp(1512373318,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T07:41:58Z"),

"optimeDurableDate"?:?ISODate("2017-12-04T07:41:58Z"),

"lastHeartbeat"?:?ISODate("2017-12-04T07:42:08.637Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T07:42:07.648Z"),

"pingMs"?:?NumberLong(0),

"syncingTo"?:?"172.20.6.10:21000",

"configVersion"?:?1

},

{

"_id"?:?2,

"name"?:?"172.20.6.12:21000",

"health"?:?1,

"state"?:?2,

"stateStr"?:?"SECONDARY",

"uptime"?:?42,

"optime"?:?{

"ts"?:?Timestamp(1512373318,?1),

"t"?:?NumberLong(1)

},

"optimeDurable"?:?{

"ts"?:?Timestamp(1512373318,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T07:41:58Z"),

"optimeDurableDate"?:?ISODate("2017-12-04T07:41:58Z"),

"lastHeartbeat"?:?ISODate("2017-12-04T07:42:08.637Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T07:42:07.642Z"),

"pingMs"?:?NumberLong(0),

"syncingTo"?:?"172.20.6.10:21000",

"configVersion"?:?1

}

],

"ok"?:?1

}

此時config server集群已經配置完成,mongodb-1為primary,mongdb-2/mongodb-3為secondary

2.2.4 配置shard集群

三臺服務器均進行shard集群配置

shard1配置

cat?>/data/mongodb/shard1/conf/shard.conf?<

dbpath=/data/mongodb/shard1/data

logpath?=?/data/mongodb/shard1/log/shard1.log

port?=?22001

logappend?=?true

nohttpinterface?=?true

fork?=?true

oplogSize?=?4096

journal?=?true

#engine?=?wiredTiger

#cacheSizeGB?=?38G

smallfiles=true

shardsvr=true????????#shard服務器

replSet=shard1????????#副本集名稱shard1

EOF

mongod?-f?/data/mongodb/shard1/conf/shard.conf????????#啟動shard服務

查看此時服務已經正常啟動,shard1的22001端口已經正常監聽,接下來登錄mongodb-1服務器進行shard1副本集初始化

mongo?172.20.6.10:22001

use?admin

config?=?{_id:"shard1",members:[

{_id:0,host:"172.20.6.10:22001"},

{_id:1,host:"172.20.6.11:22001",arbiterOnly:true},

{_id:2,host:"172.20.6.12:22001"},]

}

rs.initiate(config);

查看集群狀態,只列出了部分信息:

{

"_id"?:?0,

"name"?:?"172.20.6.10:22001",

"health"?:?1,

"state"?:?1,

"stateStr"?:?"PRIMARY",????????????#mongodb-1為primary

"uptime"?:?276,

"optime"?:?{

"ts"?:?Timestamp(1512373911,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T07:51:51Z"),

"infoMessage"?:?"could?not?find?member?to?sync?from",

"electionTime"?:?Timestamp(1512373879,?1),

"electionDate"?:?ISODate("2017-12-04T07:51:19Z"),

"configVersion"?:?1,

"self"?:?true

},

{

"_id"?:?1,

"name"?:?"172.20.6.11:22001",

"health"?:?1,

"state"?:?7,

"stateStr"?:?"ARBITER",????????????#mongodb-2為arbiter

"uptime"?:?45,

"lastHeartbeat"?:?ISODate("2017-12-04T07:51:53.597Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T07:51:51.243Z"),

"pingMs"?:?NumberLong(0),

"configVersion"?:?1

},

{

"_id"?:?2,

"name"?:?"172.20.6.12:22001",

"health"?:?1,

"state"?:?2,

"stateStr"?:?"SECONDARY",????????#mongodb-3為secondary

"uptime"?:?45,

"optime"?:?{

"ts"?:?Timestamp(1512373911,?1),

"t"?:?NumberLong(1)

},

此時shard1 副本集已經配置完成,mongodb-1為primary,mongodb-2為arbiter,mongodb-3為secondary。

同樣的操作進行shard2配置和shard3配置

注意:進行shard2的副本集初始化,在mongodb-2, 初始化shard3副本集在mongodb-3上進行操作。

shard2配置文件

cat?>/data/mongodb/shard2/conf/shard.conf?<

dbpath=/data/mongodb/shard2/data

logpath?=?/data/mongodb/shard2/log/shard2.log

port?=?22002

logappend?=?true

nohttpinterface?=?true

fork?=?true

oplogSize?=?4096

journal?=?true

#engine?=?wiredTiger

#cacheSizeGB?=?38G

smallfiles=true

shardsvr=true

replSet=shard2

EOF

mongod?-f?/data/mongodb/shard2/conf/shard.conf

shard3配置文件

cat?>/data/mongodb/shard3/conf/shard.conf?<

dbpath=/data/mongodb/shard3/data

logpath?=?/data/mongodb/shard3/log/shard3.log

port?=?22003

logappend?=?true

nohttpinterface?=?true

fork?=?true

oplogSize?=?4096

journal?=?true

#engine?=?wiredTiger

#cacheSizeGB?=?38G

smallfiles=true

shardsvr=true

replSet=shard3

EOF

mongod?-f?/data/mongodb/shard2/conf/shard.conf

在mongodb-2上進行shard2副本集初始化

mongo?172.20.6.11:22002????#登錄mongodb-2

use?admin

config?=?{_id:"shard2",members:[

{_id:0,host:"172.20.6.10:22002"},

{_id:1,host:"172.20.6.11:22002"},

{_id:2,host:"172.20.6.12:22002",arbiterOnly:true},]

}

rs.initiate(config);

查看shard2副本集狀態

{

"_id"?:?0,

"name"?:?"172.20.6.10:22002",

"health"?:?1,

"state"?:?2,

"stateStr"?:?"SECONDARY",????????#mongodb-2為secondary

"uptime"?:?15,

"optime"?:?{

"ts"?:?Timestamp(1512374668,?1),

"t"?:?NumberLong(1)

},

"optimeDurable"?:?{

"ts"?:?Timestamp(1512374668,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T08:04:28Z"),

"optimeDurableDate"?:?ISODate("2017-12-04T08:04:28Z"),

"lastHeartbeat"?:?ISODate("2017-12-04T08:04:30.527Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T08:04:28.492Z"),

"pingMs"?:?NumberLong(0),

"syncingTo"?:?"172.20.6.11:22002",

"configVersion"?:?1

},

{

"_id"?:?1,

"name"?:?"172.20.6.11:22002",

"health"?:?1,

"state"?:?1,

"stateStr"?:?"PRIMARY",????????#mongodb-2為primary

"uptime"?:?211,

"optime"?:?{

"ts"?:?Timestamp(1512374668,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T08:04:28Z"),

"infoMessage"?:?"could?not?find?member?to?sync?from",

"electionTime"?:?Timestamp(1512374666,?1),

"electionDate"?:?ISODate("2017-12-04T08:04:26Z"),

"configVersion"?:?1,

"self"?:?true

},

{

"_id"?:?2,

"name"?:?"172.20.6.12:22002",????????#mongodb-3為arbiter

"health"?:?1,

"state"?:?7,

"stateStr"?:?"ARBITER",

"uptime"?:?15,

"lastHeartbeat"?:?ISODate("2017-12-04T08:04:30.527Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T08:04:28.384Z"),

"pingMs"?:?NumberLong(0),

"configVersion"?:?1

}

登錄mongodb-3進行shard3副本集初始化

mongo?172.20.6.12:22003????#登錄mongodb-3

use?admin

config?=?{_id:"shard3",members:[

{_id:0,host:"172.20.6.10:22003",arbiterOnly:true},

{_id:1,host:"172.20.6.11:22003"},

{_id:2,host:"172.20.6.12:22003"},]

}

rs.initiate(config);

查看shard3副本集狀態

{

"_id"?:?0,

"name"?:?"172.20.6.10:22003",

"health"?:?1,

"state"?:?7,

"stateStr"?:?"ARBITER",????????#mongodb-1為arbiter

"uptime"?:?18,

"lastHeartbeat"?:?ISODate("2017-12-04T08:07:37.488Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T08:07:36.224Z"),

"pingMs"?:?NumberLong(0),

"configVersion"?:?1

},

{

"_id"?:?1,

"name"?:?"172.20.6.11:22003",

"health"?:?1,

"state"?:?2,

"stateStr"?:?"SECONDARY",????????#mongodb-2為secondary

"uptime"?:?18,

"optime"?:?{

"ts"?:?Timestamp(1512374851,?1),

"t"?:?NumberLong(1)

},

"optimeDurable"?:?{

"ts"?:?Timestamp(1512374851,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T08:07:31Z"),

"optimeDurableDate"?:?ISODate("2017-12-04T08:07:31Z"),

"lastHeartbeat"?:?ISODate("2017-12-04T08:07:37.488Z"),

"lastHeartbeatRecv"?:?ISODate("2017-12-04T08:07:36.297Z"),

"pingMs"?:?NumberLong(0),

"syncingTo"?:?"172.20.6.12:22003",

"configVersion"?:?1

},

{

"_id"?:?2,

"name"?:?"172.20.6.12:22003",

"health"?:?1,

"state"?:?1,

"stateStr"?:?"PRIMARY",????????#mongodb-3為primary

"uptime"?:?380,

"optime"?:?{

"ts"?:?Timestamp(1512374851,?1),

"t"?:?NumberLong(1)

},

"optimeDate"?:?ISODate("2017-12-04T08:07:31Z"),

"infoMessage"?:?"could?not?find?member?to?sync?from",

"electionTime"?:?Timestamp(1512374849,?1),

"electionDate"?:?ISODate("2017-12-04T08:07:29Z"),

"configVersion"?:?1,

"self"?:?true

}

此時shard集群全部已經配置完畢。

2.2.5 配置路由服務器mongos

目前三臺服務器的配置服務器和分片服務器均已啟動,配置三臺mongos服務器

由于mongos服務器的配置是從內存中加載,所以自己沒有存在數據目錄configdb連接為配置服務器集群

cat?>/data/mongodb/mongos/conf/mongos.conf<

--logpath=/data/mongodb/mongos/log/mongos.log

logappend=true

port?=?20000

maxConns?=?1000

configdb=replconf/172.20.6.10:21000,172.20.6.11:21000,172.20.6.12:21000???#制定config?server集群

fork?=?true

EOF

mongos?-f?/data/mongodb/mongos/conf/mongos.conf????????#啟動mongos服務

目前config server集群/shard集群/mongos服務均已啟動,但此時為設置分片,還不能使用分片功能。需要登錄mongos啟用分片

登錄任意一臺mongos

mongo?172.20.6.10:20000

use?admin

db.runCommand({addshard:"shard1/172.20.6.10:22001,172.20.6.11:22001,172.20.6.12:22001"})

db.runCommand({addshard:"shard2/172.20.6.10:22002,172.20.6.11:22002,172.20.6.12:22002"})

db.runCommand({addshard:"shard3/172.20.6.10:22003,172.20.6.11:22003,172.20.6.12:22003"})

查看集群

三、 測試

目前配置服務、路由服務、分片服務、副本集服務都已經串聯起來了,此時進行數據插入,數據能夠自動分片。連接在mongos上讓指定的數據庫、指定的集合分片生效。

注意:設置分片需要在admin數據庫進行

use?admin

db.runCommand(?{?enablesharding?:"kaliarchdb"});????#開啟kaliarch庫分片功能

db.runCommand(?{?shardcollection?:?"kaliarchdb.table1",key?:?{_id:"hashed"}?}?)????#指定數據庫里需要分片的集合tables和片鍵_id

設置kaliarchdb的 table1 表需要分片,根據 _id 自動分片到 shard1 ,shard2,shard3 上面去。

查看分片信息

測試插入數據

use?kaliarchdb;

for?(var?i?=?1;?i?<=?100000;?i++)?db.table1.save({_id:i,"test1":"testval1"});

查看分片情況:(省去部分信息)

db.table1.stats()

{

"sharded"?:?true,

"capped"?:?false,

"ns"?:?"kaliarchdb.table1",

"count"?:?100000,????????#總count

"size"?:?3800000,

"storageSize"?:?1335296,

"totalIndexSize"?:?4329472,

"indexSizes"?:?{

"_id_"?:?1327104,

"_id_hashed"?:?3002368

},

"avgObjSize"?:?38,

"nindexes"?:?2,

"nchunks"?:?6,

"shards"?:?{

"shard1"?:?{

"ns"?:?"kaliarchdb.table1",

"size"?:?1282690,

"count"?:?33755,????????#shard1的count數

"avgObjSize"?:?38,

"storageSize"?:?450560,

"capped"?:?false,

......

"shard2"?:?{

"ns"?:?"kaliarchdb.table1",

"size"?:?1259434,

"count"?:?33143,????????#shard2的count數

"avgObjSize"?:?38,

"storageSize"?:?442368,

"capped"?:?false,

.......

"shard3"?:?{

"ns"?:?"kaliarchdb.table1",

"size"?:?1257876,

"count"?:?33102,????????????#shard3的count數

"avgObjSize"?:?38,

"storageSize"?:?442368,

"capped"?:?false,

此時架構中的mongos,config server,shard集群均已經搭建部署完畢,在實際生成環境話需要對前端的mongos做高可用來提示整體高可用。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容