抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文主要学习了什么是分片,以及如何配置简单的分片集群。

环境

Windows 10 企业版 LTSC 21H2
MongoDB 6.0.21

1 介绍

1.1 背景

服务上线后,由于用户数量和业务规模的增长,对数据存储空间的需求也越来越大。有两种方法可解决系统增长问题:

  • 垂直扩展(Vertical Scaling)意味着增加单个服务器的容量,例如使用更强大的CPU,添加更多RAM或增加存储空间量,可用技术所存在的限制可能会导致单个机器对给定工作负载来说不够强大。此外,基于云的提供商存在基于可用硬件配置的硬上限。因此,垂直扩展存在实际的最大值。
  • 水平扩展(Horizontal Scaling)意味着划分系统数据集并加载多个服务器,添加其他服务器以根据需要增加容量。虽然单个机器的总体速度或容量可能不高,但每台机器处理整个工作负载的子集,可能提供比单个高速大容量服务器更高的效率。扩展部署容量只需要根据需要添加额外的服务器,这可能比单个机器的高端硬件的总体成本更低。但代价在于它会增大部署的基础设施与维护的复杂性。

1.2 概念

分片(Sharding)是指将数据拆分,将其分散存在不同的机器上的过程,有时也用分区(Partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存更多的数据,处理更多的负载。

MongoDB支持通过分片进行水平扩展。

2 组成

MongoDB的分片集群(Sharded Cluster)由以下组件构成:

  • 分片服务器(Shard)
  • 配置服务器(Config Server)
  • 路由服务器(Router)

2.1 分片服务器(Shard Server)

存储分片集群中分片数据的子集,集群的分片服务器共同保存集群的整个数据集,分片服务器必须部署为副本集。

2.2 配置服务器(Config Server)

存储分片集群的元数据和配置设置,配置服务器必须部署为副本集:

  • 元数据反映了分片集群内所有数据和组件的状态和组织,包括每个分片上的数据段列表以及定义数据段的范围。
  • 配置信息保存了访问控制和身份验证设置,需要将admin数据库和config数据库存在配置服务器上。

每个分片集群必须拥有自己的配置服务器,请勿对不同的分片集群使用相同的配置服务器。

配置服务器副本集(Config Server Replica Set,CSRS)有以下限制:

  • 不能有仲裁节点。
  • 不得包含延迟节点。
  • 必须构建索引,即buildIndexes都应为false。

2.3 路由服务器(Router Server)

路由服务器通常由mongos实例实现,负责将客户端的请求转发到正确的分片,并汇总各个分片的响应结果返回给客户端。

路由服务器会定时缓存配置服务器的元数据,用于查询请求的分片键,通过分片键转发到对应的分片。

路由服务器的工作流程可以分为以下几个步骤:

  1. 接收客户端的请求。
  2. 根据缓存的元数据查询分片键,确定请求应该发送到哪个分片。
  3. 将请求分发到相应的分片。
  4. 汇总各个分片的响应结果,并将最终结果返回给客户端。

3 架构

建议生产配置:

  • 部署多个路由服务器。
  • 部署3个或以上配置服务器副本集。
  • 部署3个或以上分片服务器副本集。

建议开发配置:

  • 部署一个路由服务器。
  • 部署1个配置服务器副本集。
  • 部署1个分片服务器副本集。

4 配置

配置2个分片服务器副本集,采用1主节点1从节点1仲裁节点的配置。

配置1个配置服务器副本集,不能使用仲裁节点,采用1主节点2从节点配置。

配置1个路由服务器,使用mongos服务,不是mongod服务。

4.1 第1个分片服务器副本集

4.1.1 创建节点

创建目录,修改mongod.conf配置文件,修改目录位置和端口,增加副本集和分片角色的配置:

mongod.conf
1
2
3
4
5
6
7
replication:
# 副本集的名称
replSetName: srs01

sharding:
# 分片角色 shardsvr-分片服务器 configsvr-配置服务器
clusterRole: shardsvr

进入安装MongoDB的bin目录,通过mongod.exe文件启动:

cmd
1
2
3
mongod.exe -f D:\momashanhe\mongodb\srs01_27001\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\srs01_27002\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\srs01_27003\mongod.conf

4.1.2 配置副本集

连接节点:

cmd
1
mongosh.exe mongodb://127.0.0.1:27001

启动副本集:

cmd
1
rs.initiate()

添加从节点:

cmd
1
rs.add("127.0.0.1:27002")

明确设置默认写关注:

cmd
1
2
3
4
5
6
db.adminCommand({
"setDefaultRWConcern": 1,
"defaultWriteConcern": {
"w": "majority"
}
})

添加仲裁节点:

cmd
1
rs.addArb("127.0.0.1:27003")

4.2 第2个分片服务器副本集

4.2.1 创建节点

创建目录,修改mongod.conf配置文件,修改目录位置和端口,增加副本集和分片角色的配置:

mongod.conf
1
2
3
4
5
6
7
replication:
# 副本集的名称
replSetName: srs02

sharding:
# 分片角色 shardsvr-分片服务器 configsvr-配置服务器
clusterRole: shardsvr

进入安装MongoDB的bin目录,通过mongod.exe文件启动:

cmd
1
2
3
mongod.exe -f D:\momashanhe\mongodb\srs02_27004\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\srs02_27005\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\srs02_27006\mongod.conf

4.2.2 配置副本集

连接节点:

cmd
1
mongosh.exe mongodb://127.0.0.1:27004

启动副本集:

cmd
1
rs.initiate()

添加从节点:

cmd
1
rs.add("127.0.0.1:27005")

明确设置默认写关注:

cmd
1
2
3
4
5
6
db.adminCommand({
"setDefaultRWConcern": 1,
"defaultWriteConcern": {
"w": "majority"
}
})

添加仲裁节点:

cmd
1
rs.addArb("127.0.0.1:27006")

4.3 配置服务器副本集

4.3.1 创建节点

创建目录,修改mongod.conf配置文件,修改目录位置和端口,增加副本集和分片角色的配置:

mongod.conf
1
2
3
4
5
6
7
replication:
# 副本集的名称
replSetName: csrs

sharding:
# 分片角色 shardsvr-分片服务器 configsvr-配置服务器
clusterRole: configsvr

进入安装MongoDB的bin目录,通过mongod.exe文件启动:

cmd
1
2
3
mongod.exe -f D:\momashanhe\mongodb\csrs_27007\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\csrs_27008\mongod.conf
mongod.exe -f D:\momashanhe\mongodb\csrs_27009\mongod.conf

4.3.2 配置副本集

连接节点:

cmd
1
mongosh.exe mongodb://127.0.0.1:27007

启动副本集:

cmd
1
rs.initiate()

添加从节点:

cmd
1
2
rs.add("127.0.0.1:27008")
rs.add("127.0.0.1:27009")

4.4 路由服务器

4.4.1 配置路由

创建router_27010目录,在目录下创建log目录和mongos.conf配置文件:

mongos.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# mongos.conf

systemLog:
# 日志输出目的地,表示输出到日志文件,如果不指定,则会输出到标准输出中
destination: file
# 日志路径,启动后自动创建
path: D:\momashanhe\mongodb\router_27010\log\mongos.log
# 重启后如何记录日志,如果为true则将日志添加到尾部,如果为false则备份日志并创建新文件,默认为false
logAppend: true

net:
# 设置MongoDB的端口
port: 27010
# 设置可以访问的ip地址,多个用逗号分隔
bindIp: 127.0.0.1

sharding:
# 配置节点的配置服务器副本集
configDB: csrs/127.0.0.1:27007,127.0.0.1:27008,127.0.0.1:27009

进入安装MongoDB的bin目录,通过mongos.exe文件启动:

cmd
1
mongos.exe -f D:\momashanhe\mongodb\router_27010\mongos.conf

4.4.2 连接路由

连接路由服务器:

cmd
1
mongosh.exe mongodb://127.0.0.1:27010

此时是无法写入数据的,因为还没有关联分片服务器副本集。

建议不要直接在分片服务器副本集操作数据,而是通过路由服务器操作数据。

多台服务器配置了相同的配置服务副本集,因此配置分片只需要在其中一台操作,其他服务器就可以直接查看数据和分片信息,不需要重新配置。

4.5 配置分片

4.5.1 添加分片

使用命令添加分片:

bson
1
sh.addShard(<url>)

含义:

名称 类型 说明
url 字符串 副本集/IP地址:端口的形式传入参数。

添加分片:

bson
1
2
sh.addShard("srs01/127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003");
sh.addShard("srs02/127.0.0.1:27004,127.0.0.1:27005,127.0.0.1:27006");

添加分片如果提示:

bson
1
MongoServerError[OperationFailed]: Cannot add xxx as a shard since the implicit default write concern on this shard is set to {w : 1}, because number of arbiters in the shard's configuration caused the number of writable voting members not to be strictly more than the voting majority. Change the shard configuration or set the cluster-wide write concern using the setDefaultRWConcern command and try again.

这是因为当前mongos设置的写入安全机制defaultWriteConcern是majority表示多数确认,这意味着当进行写操作时,至少要有超过半数的数据节点确认写操作成功,才会返回成功的响应。目前有3个节点,半数的节点数量为2,超过半数也就是至少要有3个节点写入成功才行,但是传入了仲裁节点,导致3个节点中只有2个可写数据的节点,怎么也不会写成功,所以导致失败。

解决方是将写入安全级别调低,然后再添加分片:

bson
1
2
3
4
db.adminCommand({
"setDefaultRWConcern": 1,
"defaultWriteConcern": { "w": 1 }
});

4.5.2 查看分片状态

使用命令查看分片状态:

bson
1
sh.status();

4.5.3 集合分片

使用命令对集合分片:

bson
1
sh.shardCollection(<namespace>, <key>, <unique>)

含义:

名称 类型 说明
namespace 字符串 数据库.集合的形式指定命名空间。
key 文档 { 属性名: 1 }或者{ 属性名: "hashed" }的形式指定一个或多个字段用作分片键的文档。
unique 布尔 是否强制底层索引使用唯一约束,默认为false,true表示强制唯一,false表示不强制唯一。在使用哈希分片键时,不能设置为true

对集合分片:

bson
1
sh.shardCollection("school.student", { _id: "hashed" });

4.5.4 测试分片

切换数据库:

bson
1
use school;

循环插入数据:

bson
1
2
3
for (var i=1; i<=1000; i++) {
db.student.insert({ _id: i + "", name: "test_" + i });
}

查看分片键分布状态:

bson
1
db.student.getShardDistribution();

显示数据被均匀分到两个分片上了:

bson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Shard srs02 at srs02/127.0.0.1:27004,127.0.0.1:27005
{
data: '18KiB',
docs: 503,
chunks: 2,
'estimated data per chunk': '9KiB',
'estimated docs per chunk': 251
}
---
Shard srs01 at srs01/127.0.0.1:27001,127.0.0.1:27002
{
data: '17KiB',
docs: 497,
chunks: 2,
'estimated data per chunk': '8KiB',
'estimated docs per chunk': 248
}
---
Totals
{
data: '35KiB',
docs: 1000,
chunks: 4,
'Shard srs02': [
'50.34 % data',
'50.3 % docs in cluster',
'36B avg obj size on shard'
],
'Shard srs01': [
'49.65 % data',
'49.7 % docs in cluster',
'36B avg obj size on shard'
]
}

评论