在今天的世界上,数据处理能力不仅需要速度,还需要持久性及可靠性以及高可用性。在这篇博客中,我们将探讨复制和分片等关键概念,以及MongoDB是如何结合这些机制来实现性能和持久性的同时保证可靠性。我们还将探讨如何配置集群以确保容错性的同时实现高可用性,并介绍手动设置MongoDB集群的实际操作。
我们为什么需要多个数据库服务器?随着数据量的增长,我们面临的主要挑战有:性能和耐久性。单个数据库服务器可能无法处理高流量或确保数据始终可用,特别是在系统出现故障时。为了解决这些问题,我们会在MongoDB集群中使用复制和分片技术。
- 耐用性 保证即使硬件出现故障也不会丢失数据。
- 性能 使工作负载分配到多个服务器上,从而实现更快的数据读取。
数据复制是MongoDB中将数据复制到多个服务器的过程,这有助于提升数据的持久性和容错能力。一个MongoDB集群通常由多个节点(服务器)组成,其中一个节点被指定为主节点(主服务器),其余节点为从节点(从服务器)。
- 主节点:这里执行所有的写操作。
- 从节点:这些节点会复制主节点的数据,并可用于读操作。
当主节点失败时,MongoDB 会在剩余的节点之间发起一个 选举 来选择一个新的主节点。这确保了系统自动运行,无需人工干预。
高可用性和故障容错通过复制,MongoDB 实现了高度可用性。由于数据被复制到了多个节点,系统可以容忍故障。如果一个节点宕机了,其他节点可以接管。这种架构不仅保证了系统的 可用性,还提供了 数据持久性 的保障。
MongoDB中分片的作用是什么虽然复制负责持久性,sharding通过将数据分布到多个节点上,提升了性能。从而使MongoDB能够通过将数据拆分到不同服务器上来水平扩展大规模数据集。
分片工作原理在 MongoDB 中,数据分片是根据所谓的分片键(例如名称、年龄或电话号码等属性)来分布数据。这个键决定了数据如何划分到不同的节点上。
比如说:
- 这个节点存放年龄段为:1到30岁。
- 这个节点存放年龄段为:31到60岁。
- 这个节点存放年龄段为:61到90岁。
分片键是根据最常查询的属性来选定的。比如说,如果用户主要是按年龄搜索,年龄就会作为分片键。
这是一个JavaScript对象,包含两个属性:名字为'Eric',年龄为30岁。
在这个例子中,如果 age 是分片键,MongoDB 会将文档存储在与 30 年龄段相关的节点上。因此,读取操作会更快,因为每个查询都会根据键被定向到相关的分片。
分片和复制的结合仅靠分片可以提升读取性能,但它并不能确保系统的可用性和数据的持久性。为解决这一问题,MongoDB 将 分片 和 复制 结合起来使用。每个分片都配有自己的副本集,以确保数据不会丢失且始终保持可用,即使某个分片出现故障也不受影响。
例如,我们有一个节点(节点 B),它存储了 31 到 60 岁年龄段的数据。在节点 B 的后面,有两个节点,节点 M 和节点 N,复制它的数据来确保数据的持久性。如果节点 B 出现故障,其中一个备援节点(M 或 N)可以接手。
这种sharding和replication的结合让MongoDB能够同时应对性能和数据持久性的问题,无论是在大规模部署中。
MongoDB 集群架构 1. MongoDB 路由 (mongos)MongoDB Router (mongos) 作为客户端和分片间的桥梁。它不存储任何数据,但发挥着关键作用,根据分片键将查询和写操作引导至正确的分片。
如果没有 mongos,客户端就需要知道每份数据的位置,这会大大增加数据库操作的复杂度。mongos 处理这种复杂性,让客户端可以无缝地与集群进行交互。
2. 元数据和配置中心这些 配置节点(元数据服务器)存储了集群架构的所有元数据,包括数据在各个分片上的分布。它们记录了数据是如何被分割的,以及每个分片包含的数据部分。
配置服务器集群非常重要,因为没有它,mongos 就无法正确地将数据路由,系统也不清楚数据在各个分片上的分布情况。
3. 分片服务器分片是用于实际存储数据的数据库服务器。每个分片都是一个副本集,包含一个主节点和若干从节点。分片将数据分割成更小、更易管理的部分,每个分片存储一部分数据。
为什么需要分片服务器呢?
- 数据分布:分片将数据分散到多个节点上,实现了水平扩展性。这意味着数据库可以通过增加更多的机器来扩展,而不是增大单个机器的容量。
- 容错性和持久性:因为每个分片都是一个副本集,主节点处理写操作,从节点复制数据。如果主节点失败,选举过程会自动提升一个从节点为主节点。
- 可扩展性:分片通过将大数据量分割成更小的部分,并分布在多个服务器上,使集群能够高效处理大量数据。这确保了即使是庞大的数据集也能被高效管理。
当客户端向 MongoDB 发送请求数据时,
- mongos 收到请求。
- mongos 会查询 配置服务器 找出包含所需数据的分片。
- 然后把请求发送给相关的 分片服务器 处理。
在进行写操作时,mongos 将数据发送到相应的分片中的主节点。从节点复制数据以确保容错性和持久性。
MongoDB集群的实际设置现在我们理解了MongoDB架构的组成部分,接下来我们就用Docker在AWS EC2实例上搭建一个MongoDB集群。
MongoDB 集群搭建步骤如下:步骤1:在Amazon Linux上安装Docker容器。
第一步是安装 Docker 引擎,这样我们就可以开始搭建我们的集群了。
在终端中输入以下命令:
yum install docker -y
这将安装Docker并自动确认安装包。
步骤2:安装MongoDB工具包。
- 要安装
mongodb-org
,你首先需要添加 yum 仓库,然后创建一个/etc/yum.repos.d/mongodb-org-7.0.repo
文件,这样你就可以通过yum
直接安装 MongoDB 了。
[mongodb-org-7.0]
name=MongoDB 存储库
baseurl=https://repo.mongodb.org/yum/amazon/2023/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc # gpgkey URL
- 要安装最新稳定版的 MongoDB,请在终端中运行如下命令:
sudo yum install -y mongodb-org
- 运行一下
mongosh
命令来确认:
- 下一步是安装 docker-compose,因为我们将在一个组中分别运行分片服务器或配置服务器。
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose version
命令解释:
# 下载并安装docker-compose的最新版本到/usr/local/bin/docker-compose
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# 使docker-compose可执行
sudo chmod +x /usr/local/bin/docker-compose
# 检查docker-compose的版本
docker-compose version
第4步:启动配置节点。
- 启动配置服务器的第一步是创建一个名为
configsvr.yaml
的 Docker Compose 文件,在这个文件中,我们描述每个容器的名称、使用的镜像名以及运行在容器内的命令。
version: '3'
services:
cfgsvr1:
container_name: cfgsvr1
image: mongo
command: mongod --configsvr --replSet cfgrs --port 27017 --dbpath /data/db
ports:
- 40001:27017
volumes:
- cfgsvr1:/data/db
cfgsvr2:
container_name: cfgsvr2
image: mongo
command: mongod --configsvr --replSet cfgrs --port 27017 --dbpath /data/db
ports:
- 40002:27017
volumes:
- cfgsvr2:/data/db
cfgsvr3:
container_name: cfgsvr3
image: mongo
command: mongod --configsvr --replSet cfgrs --port 27017 --dbpath /data/db
ports:
- 40003:27017
volumes:
- cfgsvr3:/data/db
volumes:
cfgsvr1: {}
cfgsvr2: {}
cfgsvr3: {}
-
该命令用来配置它们作为副本集,以确保高可用性。
-
这些容器的端口号是
**40001, 40002, 40003**
,并暴露出来。 - 配置服务器启动:
docker-compose -f configsvr.yaml up -d # 使用 configsvr.yaml 配置文件启动服务
- 尝试使用
mongosh
命令连接到一个服务器。
mongosh <系统IP地址>(例如:192.168.1.1):40001
- 虽然成功连接了,但在运行命令时会出现错误。
- 这是因为这些节点互相不认识,因此即使配置为副本节点,也无法正常工作,因为它们无法参与选举,没有主从之分,任何事情都无法进行。
启动副本集:
rs.initiate(
{
_id: "cfgrs",
configsvr: true,
members: [
{ _id : 0, host : "172.31.35.127:40001" },
{ _id : 1, host : "172.31.35.127:40002" },
{ _id : 2, host : "172.31.35.127:40003" }
]
}
)
rs.status()
这个命令会告诉你关于副本集的全部信息,比如已添加了多少个副本,选举是否有争议,哪个节点将成为主节点(primary),哪个将成为从节点(secondary)。通常,执行这些步骤的节点将成为主节点。
第五步:设置分片服务器。- 我们需要再次创建一个 Docker Compose 文件
shard1svr.yaml
。每个分片服务器也将有自己的副本集,以确保持久性。
version: '3'
services:
shard1svr1:
container_name: shard1svr1 # 容器名称为shard1svr1
image: mongo
command: mongod --shardsvr --replSet shard1rs --port 27017 --dbpath /data/db
ports:
- 50001:27017 # 端口映射为50001:27017
volumes:
- shard1svr1:/data/db # 数据卷为shard1svr1:/data/db
shard1svr2:
container_name: shard1svr2 # 容器名称为shard1svr2
image: mongo
command: mongod --shardsvr --replSet shard1rs --port 27017 --dbpath /data/db
ports:
- 50002:27017 # 端口映射为50002:27017
volumes:
- shard1svr2:/data/db # 数据卷为shard1svr2:/data/db
shard1svr3:
container_name: shard1svr3 # 容器名称为shard1svr3
image: mongo
command: mongod --shardsvr --replSet shard1rs --port 27017 --dbpath /data/db
ports:
- 50003:27017 # 端口映射为50003:27017
volumes:
- shard1svr3:/data/db # 数据卷为shard1svr3:/data/db
volumes:
shard1svr1: {}
shard1svr2: {}
shard1svr3: {} # 定义数据卷
- 启动配置服务器,
运行 docker-compose -f shard1svr.yaml up -d
.
- 我们需要再次遵循相同的步骤,并进入其中一个分片服务器内部来启动副本集。
mongosh <系统IP地址>:50001
- 咱们用
rs.status()
查看状态
- 现在这是第一个分片集群,接下来我们还需要用同样的步骤创建另一个分片集群。
- Docker Compose 文件和所需命令如下所示:
version: '3'
services:
shard2svr1:
container_name: 容器名称shard2svr1
image: mongo
command: mongod --shardsvr --replSet shard2rs --port 27017 --dbpath /data/db
ports:
- 50004:27017
volumes:
- shard2svr1:/data/db
shard2svr2:
container_name: 容器名称shard2svr2
image: mongo
command: mongod --shardsvr --replSet shard2rs --port 27017 --dbpath /data/db
ports:
- 50005:27017
volumes:
- shard2svr2:/data/db
shard2svr3:
container_name: 容器名称shard2svr3
image: mongo
command: mongod --shardsvr --replSet shard2rs --port 27017 --dbpath /data/db
ports:
- 50006:27017
volumes:
- shard2svr3:/data/db
volumes:
shard2svr1: {}
shard2svr2: {}
shard2svr3: {}
docker-compose -f shard2svr.yaml up -d
运行 shard2svr.yaml
配置文件中的 Docker Compose 服务,并将其置于后台 (-d
参数)。
mongosh <系统IP地址>:50004 (启动MongoDB shell连接到指定的系统IP地址和端口)
rs.initiate(
{
_id: "shard2rs",
members: [
{ _id : 0, host : "172.31.35.127:50004" },
{ _id : 1, host : "172.31.35.127:50005" },
{ _id : 2, host : "172.31.35.127:50006" }
]
}
)
rs.status()
第六步:启动 MongoDB 路由器程序 (mongos):
下一步是设置mongos路由,它会将客户端请求导向合适的分片。
- 编写一个供 mongos 服务器使用的 Docker Compose 文件。
version: '3'
services:
mongos:
container_name: mongos
image: mongo
command: mongos --configdb cfgrs/172.31.35.127:40001,172.31.35.127:40002,172.31.35.127:40003 --bind_ip 0.0.0.0 --port 27017
ports:
- 60000:27017
在这条命令里:
mongos
是路由器服务。--configdb
参数设置了配置服务器副本集及其服务器地址。- 启动
mongos
。
docker-compose -f mongos.yaml up -d # 启动 MongoDB 服务器(守护进程模式)
- 请连接到 mongos 服务器。
sh.status()
这个命令用来检查分片的状态信息。
- 现在没有可用的分片了,所以我们得添加一些。
// 添加碎片 "shard1rs/172.31.35.127:50001,172.31.35.127:50002,172.31.35.127:50003"
sh.addShard("shard1rs/172.31.35.127:50001,172.31.35.127:50002,172.31.35.127:50003")
- 现在在 shards 列中增加了一个分片。
- 同样,我们也将增加第二个分片群。
在用户数据库中开启分片功能。
启用分片 "userdb"
- 在数据库启用分片后,我们也需要在集合启用分片,否则数据将不会按照预期分布。为此,我们可以通过以下命令来创建集合。
使用sh.shardCollection命令(将'userdb.persons'集合根据'age'字段使用哈希算法进行分片)。
- 在这里,
userdb
是我们的数据库,persons
是我们的集合,age
是我们的分片关键字,而hashed
是一种用于将数据根据不同分片存储的算法。
我们来看看 persons
这个集合的分片分布情况,看看每个分片里存了多少数据。
执行这个命令来获取人员的分片分布: db.persons.getShardDistribution()
- 在存储数据方面,你会看到这里的一些变化,这会告诉你数据将存放在哪个位置。
将一个名为 "Harsh",年龄为 20 的人插入到 persons 集合中。
db.persons.insert({name: "Harsh", age: 20})
将{name: 'Jack', age: 11}插入到persons集合中
db.persons.insert({name: "Jack", age: 11})
- 从这些值中,我们知道两个文档都存储在shard2中。
- 我们现在插入一个文档吧。
将{name: 'Jack', age: 5}这个对象插入到persons集合中
这里的数据显示是存储在 shard1 中,这些决策是根据分片键 age
来决定的。
MongoDB的集群架构——包括mongos路由服务器、配置服务器和分片服务器——设计用于在大规模情况下提供高性能、高可用性和容错性。通过将数据分布在多个分片上并在节点之间复制数据,MongoDB确保系统既可扩展又持久可靠。
分片提升性能,复制增强容错性的结合让MongoDB成为处理大规模的、关键任务应用的强大解决方案。
共同学习,写下你的评论
评论加载中...
作者其他优质文章