阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MongoDB集群架构之分片架构

247次阅读
没有评论

共计 14513 个字符,预计需要花费 37 分钟才能阅读完成。

本文介绍了热门的 NoSQL 数据库 Mongodb 的分片架构模式的相关概念以及分片环境搭建方法。分片就是在分布式数据架构中常见的 Sharding 这个词。Mongodb 分片的方式包括范围分片、哈希分片和标签分片三种。

1. 分片相关概念

Mongodb 分片是什么?

分片即 sharding。在 Mongodb 中,一个集合可以根据特定的规则将其数据分成几个不同的部分,然后每个组成部分分布在不同的 Mongodb 服务器上。在查询时,自动从这些组成部分中查询并给给出汇总结果。

分片跟副本集是不同的概念。

分片后,每个服务器上的数据只是一个集合的一部分数据,必须将所有服务器上的数据集中后才能得到完整的数据。

副本集方式部署时,每个服务器上的数据都是完整的,不需要汇总即可得到一个集合的完整数据。

分片方式部署的节点结构。

在 Mongodb 分片方式部署时,需要三种类型的节点:

分片服务器。用于实际存放集合的数据。直接查询某个分片服务器是不能得到一个集合的完整数据的。至少应该有 2 个分片服务器。

配置服务器。用于存放各种配置数据。至少应该有 3 个配置服务器以副本集方式部署。

路由服务器。用于定位分片并向外提供数据服务。直接查询路由服务器的数据可以得到一个集合的完整数据。至少应该有 2 个路由服务器。

Mongodb 分片的三种应用方式。

范围分片。使用集合的某个键作为分片字段,根据范围分片。

哈希分片。使用集合的某个键作为分片字段,根据哈希值分片。

标签分片。使用集合的某个键作为分片字段,根据标签值分片。

2. 分片环境搭建

为了操作方便,假定所有服务器均在同一个机器上运行。

在搭建 Mongodb 分片方式的集群时,按照以下步骤进行。

(1)创建如图所示的目录结构,每个数字目录代表一个服务器所使用的端口。

MongoDB 集群架构之分片架构

图 1

config 目录中的端口用于配置服务器。route 目录中的端口用于路由服务器。shard 目录中的端口用于分片服务器。因此,这个 mongodb 集群中总共会运行 9 个 mongodb 服务器,每种类型的服务器各有 3 个。

(2)编写配置服务器的启动脚本。

MongoDB 集群架构之分片架构

图 2

(3)编写分片服务器的启动脚本。

MongoDB 集群架构之分片架构

图 3

编写路由服务器的启动脚本。

MongoDB 集群架构之分片架构

图 4

(5)启动配置服务器节点。

首先应该启动配置服务器节点,再启动分片节点,最后启动路由节点。

[root@coe2coe data]# ./config/startconfig.sh  27117 27118 27119

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27117}

about to fork child process, waiting until server is ready for connections.

forked process: 6403

child process started successfully, parent exiting

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27118}

about to fork child process, waiting until server is ready for connections.

forked process: 6437

child process started successfully, parent exiting

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27119}

about to fork child process, waiting until server is ready for connections.

forked process: 6471

child process started successfully, parent exiting

3 个配置服务器需要配置成为副本集的方式,因此将它们组成一个副本集,以 27117 节点为主节点,另外两个节点均为从节点 (SECONDARY)。具体配置方式请参考之前的关于副本集的博客。此处不再赘述。

(6)启动分片服务器节点。

[root@coe2coe data]# ./shard/startshard.sh 27017 27018 27019

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27017}

about to fork child process, waiting until server is ready for connections.

forked process: 6324

child process started successfully, parent exiting

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27018}

about to fork child process, waiting until server is ready for connections.

forked process: 6350

child process started successfully, parent exiting

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27019}

about to fork child process, waiting until server is ready for connections.

forked process: 6376

child process started successfully, parent exiting

(7)启动路由服务器节点。

[root@coe2coe data]# ./route/startroute.sh  11.1.1.11:27117,11.1.1.11:27118,11.1.1.11:27119   27217 27218 27219

CONFIG_SERVERS:{11.1.1.11:27117,11.1.1.11:27118,11.1.1.11:27119}

DBPORTS:{27217}

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27217}

about to fork child process, waiting until server is ready for connections.

forked process: 6643

child process started successfully, parent exiting

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27218}

about to fork child process, waiting until server is ready for connections.

forked process: 6674

child process started successfully, parent exiting

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27219}

about to fork child process, waiting until server is ready for connections.

forked process: 6705

child process started successfully, parent exiting

启动路由服务器节点后需要将三个分片服务器节点加入到这个路由中。

[root@coe2coe data]# mongo  –quiet –port=27217

mongos> sh.addShard(“11.1.1.11:27017”);

{

“shardAdded” : “shard0000”,

“ok” : 1,

“operationTime” : Timestamp(1538403870, 4),

“$clusterTime” : {

“clusterTime” : Timestamp(1538403870, 4),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addShard(“11.1.1.11:27018”);

{

“shardAdded” : “shard0001”,

“ok” : 1,

“operationTime” : Timestamp(1538403879, 3),

“$clusterTime” : {

“clusterTime” : Timestamp(1538403879, 4),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addShard(“11.1.1.11:27019”);

{

“shardAdded” : “shard0002”,

“ok” : 1,

“operationTime” : Timestamp(1538403887, 2),

“$clusterTime” : {

“clusterTime” : Timestamp(1538403887, 2),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

此时可以查看分片状态:

mongos> sh.status();

— Sharding Status — 

  sharding version: {

  “_id” : 1,

  “minCompatibleVersion” : 5,

  “currentVersion” : 6,

  “clusterId” : ObjectId(“5bb22c83322f90f844d3defc”)

  }

  shards:

        {“_id” : “shard0000”,  “host” : “11.1.1.11:27017”,  “state” : 1}

        {“_id” : “shard0001”,  “host” : “11.1.1.11:27018”,  “state” : 1}

        {“_id” : “shard0002”,  “host” : “11.1.1.11:27019”,  “state” : 1}

  active mongoses:

        “4.0.2-76-g279a1f51b9” : 3

  autosplit:

        Currently enabled: yes

  balancer:

        Currently enabled:  yes

        Currently running:  no

        Failed balancer rounds in last 5 attempts:  0

        Migration Results for the last 24 hours: 

                No recent migrations

  databases:

        {“_id” : “config”,  “primary” : “config”,  “partitioned” : true}

三个分片节点 27017,27018,27019 均处于正常状态。至此一个正常的分片环境基本搭建完毕。

对数据库启用分片功能

在实际应用分片前,首先应该对含有需要分片的集合所在的数据库启用分片功能。在启用分片功能之后可以对其中的集合进行分片的实际操作。

MongoDB 集群架构之分片架构

图 5

3. 范围分片

对 t1 集合进行范围分片,分片字段为 shard。

MongoDB 集群架构之分片架构

图 6

4. 哈希分片

对 t1 表进行哈希分片,分片字段为 shard。

MongoDB 集群架构之分片架构

图 7

向 t2 集合中插入一些数据:

mongos> db.t2.find();

{“_id” : ObjectId(“5bb2341df116ff2bb6014822”), “name” : “a”, “shard” : 2 }

{“_id” : ObjectId(“5bb2341ff116ff2bb6014823”), “name” : “a”, “shard” : 3 }

{“_id” : ObjectId(“5bb23444f116ff2bb6014824”), “name” : “a”, “shard” : 4 }

{“_id” : ObjectId(“5bb2344af116ff2bb6014826”), “name” : “a”, “shard” : 6 }

{“_id” : ObjectId(“5bb23419f116ff2bb6014821”), “name” : “a”, “shard” : 1 }

{“_id” : ObjectId(“5bb23448f116ff2bb6014825”), “name” : “a”, “shard” : 5 }

分别通过 mongo 客户端直接向三个分片服务器节点查询,可以看到三个节点上各自有一部分数据。

[root@coe2coe route]# mongo –quiet –port=27017

> use test

switched to db test

> db.t2.find();

{“_id” : ObjectId(“5bb2344af116ff2bb6014826”), “name” : “a”, “shard” : 6 }

[root@coe2coe route]# mongo –quiet –port=27018

> use test

switched to db test

> db.t2.find();

{“_id” : ObjectId(“5bb2341df116ff2bb6014822”), “name” : “a”, “shard” : 2 }

{“_id” : ObjectId(“5bb2341ff116ff2bb6014823”), “name” : “a”, “shard” : 3 }

{“_id” : ObjectId(“5bb23444f116ff2bb6014824”), “name” : “a”, “shard” : 4 }

[root@coe2coe route]# mongo –quiet –port=27019

> use test

switched to db test

> db.t2.find();

{“_id” : ObjectId(“5bb23419f116ff2bb6014821”), “name” : “a”, “shard” : 1 }

{“_id” : ObjectId(“5bb23448f116ff2bb6014825”), “name” : “a”, “shard” : 5 }

至此哈希分片功能已经实现。

5. 标签分片

对 t3 集合进行标签分片,分片字段为 shard。

先添加几个标签。

mongos> use config

switched to db config

mongos> db.shards.find();

{“_id” : “shard0000”, “host” : “11.1.1.11:27017”, “state” : 1}

{“_id” : “shard0001”, “host” : “11.1.1.11:27018”, “state” : 1}

{“_id” : “shard0002”, “host” : “11.1.1.11:27019”, “state” : 1}

mongos> sh.addShardTag(“shard0000″,”tag1”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405808, 1),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405808, 1),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addShardTag(“shard0001″,”tag2”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405813, 1),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405813, 1),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addShardTag(“shard0002″,”tag3”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405817, 2),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405817, 2),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

为 t3 集合的 shard 字段设置标签。

shard 值小于 100 的文档分配标签 tag1,100 到 1000 的分配标签 tag2,1000 以上的分配 tag3。

mongos> use test

switched to db test

mongos> sh.addTagRange(“test.t3″, {shard:MinKey},{shard:100} ,”tag1”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405898, 1),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405898, 1),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addTagRange(“test.t3″, {shard:100},{shard:1000} ,”tag2”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405913, 1),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405913, 1),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

mongos> sh.addTagRange(“test.t3″, {shard:1000},{shard:MaxKey} ,”tag3”);

{

“ok” : 1,

“operationTime” : Timestamp(1538405924, 1),

“$clusterTime” : {

“clusterTime” : Timestamp(1538405924, 1),

“signature” : {

“hash” : BinData(0,”AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),

“keyId” : NumberLong(0)

}

}

}

向 t3 集合中增加一些文档,并直接访问三个分片节点予以验证标签分片结果。

t3 集合中的文档列表:

mongos> db.t3.find();

{“_id” : ObjectId(“5bb2368cf116ff2bb6014827”), “name” : “a”, “shard” : 1 }

{“_id” : ObjectId(“5bb23697f116ff2bb6014828”), “name” : “a”, “shard” : 99 }

{“_id” : ObjectId(“5bb2369bf116ff2bb6014829”), “name” : “a”, “shard” : 100 }

{“_id” : ObjectId(“5bb2369ef116ff2bb601482a”), “name” : “a”, “shard” : 101 }

{“_id” : ObjectId(“5bb236a4f116ff2bb601482b”), “name” : “a”, “shard” : 999 }

{“_id” : ObjectId(“5bb236a9f116ff2bb601482c”), “name” : “a”, “shard” : 1000 }

{“_id” : ObjectId(“5bb236abf116ff2bb601482d”), “name” : “a”, “shard” : 1001 }

{“_id” : ObjectId(“5bb236b3f116ff2bb601482e”), “name” : “a”, “shard” : 9999 }

分别直接访问三个分片节点:

[root@coe2coe route]# mongo –quiet –port=27017

> use test

switched to db test

> db.t3.find();

{“_id” : ObjectId(“5bb2368cf116ff2bb6014827”), “name” : “a”, “shard” : 1 }

{“_id” : ObjectId(“5bb23697f116ff2bb6014828”), “name” : “a”, “shard” : 99 }

> exit

[root@coe2coe route]# mongo –quiet –port=27018

> use test

switched to db test

> db.t3.find();

{“_id” : ObjectId(“5bb2369bf116ff2bb6014829”), “name” : “a”, “shard” : 100 }

{“_id” : ObjectId(“5bb2369ef116ff2bb601482a”), “name” : “a”, “shard” : 101 }

{“_id” : ObjectId(“5bb236a4f116ff2bb601482b”), “name” : “a”, “shard” : 999 }

> exit

[root@coe2coe route]# mongo –quiet –port=27019

> use test

switched to db test

> db.t3.find();

{“_id” : ObjectId(“5bb236a9f116ff2bb601482c”), “name” : “a”, “shard” : 1000 }

{“_id” : ObjectId(“5bb236abf116ff2bb601482d”), “name” : “a”, “shard” : 1001 }

{“_id” : ObjectId(“5bb236b3f116ff2bb601482e”), “name” : “a”, “shard” : 9999 }

> exit

结果表明,分片成功。

也可以直接通过 config 数据库查看分片情况和标签情况。

mongos> use config;

switched to db config

mongos> db.shards.find();

{“_id” : “shard0000”, “host” : “11.1.1.11:27017”, “state” : 1, “tags” : [ “tag1”] }

{“_id” : “shard0001”, “host” : “11.1.1.11:27018”, “state” : 1, “tags” : [ “tag2”] }

{“_id” : “shard0002”, “host” : “11.1.1.11:27019”, “state” : 1, “tags” : [ “tag3”] }

mongos> db.tags.find();

{“_id” : { “ns” : “test.t3”, “min” : { “shard” : { “$minKey” : 1} } }, “ns” : “test.t3”, “min” : {“shard” : { “$minKey” : 1} }, “max” : {“shard” : 100}, “tag” : “tag1” }

{“_id” : { “ns” : “test.t3”, “min” : { “shard” : 100} }, “ns” : “test.t3”, “min” : {“shard” : 100}, “max” : {“shard” : 1000}, “tag” : “tag2” }

{“_id” : { “ns” : “test.t3”, “min” : { “shard” : 1000} }, “ns” : “test.t3”, “min” : {“shard” : 1000}, “max” : {“shard” : { “$maxKey” : 1} }, “tag” : “tag3” }

6. 分片的优点

Mongodb 的分片集群架构具有以下的优点:

在分片集群架构中,可以轻松实现多点写入。

在分片架构中,可以有多个路由节点,因此,连接到任意一个路由节点均可以提供数据的读写功能。

在分片集群架构中,可以提供写数据的负载均衡。

在分片结构中,数据实际存储在分片节点中,而一个集群中可以有多个分片节点,而集合中的数据实际存储到哪一个节点是有分片的键来决定的,因此可以通过分片键来调整数据的存储位置,从而实现一定的写均衡的功能。

7. 分片的缺点

Mongodb 的分片集群架构具有以下的缺点:

在分片集群架构中,存在分片节点的单点故障问题。

每一份数据仅仅保存在某个特定的分片服务器节点中, 如果这个分片分片节点宕机,则这部分数据无法读取。解决办法稍后给出。

在分片集群架构中,如果需要读取完整的数据,只能通过路由节点读取。而数据实际存储在分片节点中,因此其中必然会多出一些节点间的网络数据传输的消耗。

8. 分片集群总控脚本

由于集群中节点个数和种类比较多,编写了一个总控脚本,用于简化集群的启动和停止以及状态查看操作。

完整脚本内容如下:

[root@coe2coe data]# cat cluster.sh

#!/bin/bash

##################################################################

#   FileName:startcluster.sh

#   Author      : coe2coe@qq.com

#   Created:2018-10-02

#   Description:http://www.cnblogs.com/coe2coe/

#################################################################

start()

{

IP=$(ip addr |grep inet |grep brd |awk -F’ ‘ ‘{ print $2}’|awk -F’/’ ‘{print $1}’)

if [“$IP” == “”]

then

  echo -e “Failed to get IP on this host.”

  exit 1

fi

CONFIG_PORTS=”27117 27118 27119″

SHARD_PORTS=”27017 27018 27019″

ROUTE_PORTS=”27217 27218 27219″

CONFIG_ADDRESSES=”$IP:27117,$IP:27118,$IP:27119″

echo -e “Starting  mongodb  cluster at {$IP}…..”

echo -e “Starting config nodes @{$CONFIG_PORTS} …” 

/data/mongo/data/config/startconfig.sh  $CONFIG_PORTS 

echo -e “Starting shard nodes @{$SHARD_PORTS}….”

/data/mongo/data/shard/startshard.sh    $SHARD_PORTS 

echo -e “Starting route nodes @{$ROUTE_PORTS} with CONFIG:{$CONFIG_ADDRESSES}….”

/data/mongo/data/route/startroute.sh    $CONFIG_ADDRESSES $ROUTE_PORTS

echo -e “===ALL DONE=====”

}

stop()

{

PIDS=$(pidof mongod mongos 2>/dev/null)

if [“$PIDS” == “”]

then

   echo -e “NO such process found!”

   exit 1

fi

echo -e “Stopping mongod and mongos:{$PIDS} ….”

kill -9 ${PIDS}

exit 0

}

status()

{

  C_PIDS=$(ps -elf |grep mongod |grep configsvr |grep -v grep |awk ‘{print $4}’ |xargs )

  D_PIDS=$(ps -elf |grep mongod |grep shardsvr |grep -v grep |awk ‘{print $4}’ |xargs )

  R_PIDS=$(ps -elf |grep mongos |grep -v grep |awk ‘{print $4}’ |xargs )

  if [“$C_PIDS” == “”]

  then

 C_STATUS=”NOT running”

  else

 C_STATUS=”Running”

  fi

  if [“$D_PIDS” == “”]

  then

 D_STATUS=”NOT running”

  else

 D_STATUS=”Running”

  fi

  if [“$R_PIDS” == “”]

  then

 R_STATUS=”NOT running”

  else

 R_STATUS=”Running”

  fi

  echo -e “config nodes:{$C_PIDS}:{${C_STATUS}}”

  echo -e “shard nodes :{$D_PIDS}:{${D_STATUS}}”

  echo -e “route nodes :{$R_PIDS}:{${R_STATUS}}”

  exit 0 

}

usage()

{

 echo -e “Usage: $0 [start|stop|status]”

 exit 1

}

case  “$1” in

start)

start

;;

stop)

stop

;;

status)

status

;;

*)

usage

;;

esac

脚本功能如下:

启动集群:

[root@coe2coe data]# ./cluster.sh start

Starting  mongodb  cluster at {11.1.1.11}…..

Starting config nodes @{27117 27118 27119} …

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27117}

about to fork child process, waiting until server is ready for connections.

forked process: 5569

child process started successfully, parent exiting

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27118}

about to fork child process, waiting until server is ready for connections.

forked process: 5652

child process started successfully, parent exiting

starting mongodb configsvr @HOMEDIR:{/data/mongo/data/config/27119}

about to fork child process, waiting until server is ready for connections.

forked process: 5737

child process started successfully, parent exiting

Starting shard nodes @{27017 27018 27019}….

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27017}

about to fork child process, waiting until server is ready for connections.

forked process: 5826

child process started successfully, parent exiting

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27018}

about to fork child process, waiting until server is ready for connections.

forked process: 5888

child process started successfully, parent exiting

starting mongodb shardsvr @HOMEDIR:{/data/mongo/data/shard/27019}

about to fork child process, waiting until server is ready for connections.

forked process: 5934

child process started successfully, parent exiting

Starting route nodes @{27217 27218 27219} with CONFIG:{11.1.1.11:27117,11.1.1.11:27118,11.1.1.11:27119}….

CONFIG_SERVERS:{11.1.1.11:27117,11.1.1.11:27118,11.1.1.11:27119}

DBPORTS:{27217}

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27217}

about to fork child process, waiting until server is ready for connections.

forked process: 5982

child process started successfully, parent exiting

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27218}

about to fork child process, waiting until server is ready for connections.

forked process: 6015

child process started successfully, parent exiting

starting mongodb routing @HOMEDIR:{/data/mongo/data/route/27219}

about to fork child process, waiting until server is ready for connections.

forked process: 6044

child process started successfully, parent exiting

===ALL DONE=====

查看集群状态:

[root@coe2coe data]# ./cluster.sh status

config nodes:{5569 5652 5737}:{Running}

shard nodes :{5826 5888 5934}:{Running}

route nodes :{5982 6015 6044}:{Running}

停止集群:

[root@coe2coe data]# ./cluster.sh stop

Stopping mongod and mongos:{5934 5888 5826 5737 5652 5569 6044 6015 5982} ….

停止集群后查看状态:

[root@coe2coe data]# ./cluster.sh status

config nodes:{}:{NOT running}

shard nodes :{}:{NOT running}

route nodes :{}:{NOT running}

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计14513字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中