搭建高可用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做高可用来提示整体高可用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容