环境amazon linux2,MongoDB版本7.0.6,AMI权限无需特定权限

由于公司业务数据的不断增长,我们开始感受到 TiDB 和 Redis 数据库在处理压力方面的局限性。因此,我们决定将 MongoDB 引入作为替代方案。我们计划搭建 MongoDB 的分片集群,以更好地应对数据存储和处理的需求。这样可以为我们的系统提供更好的扩展性和性能,从而减轻服务器的压力,并满足不断增长的数据需求。

分片简介

分片(shard)是指在将数据进行水平切分之后,将其存储到多个不同的服务器节点上的一种扩展方式。分片在概念上非常类似于应用开发中的“水平分表"。不同的点在于,MongoDB本身就自带了分片管理的能力,对于开发者来说可以做到开箱即用。

为什么要使用分片?

MongoDB复制集实现了数据的多副本复制及高可用,但是一个复制集能承载的容量和负载是有限的。 在你遇到下面的场景时,就需要考虑使用分片了∶

存储容量需求超出单机的磁盘容量。

活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能。

写IOPS超出单个MongoDB节点的写服务能力。

垂直扩容(Scale Up)VS水平扩容(Scale Out) :

垂直扩容:用更好的服务器,提高CPU处理核数、内存数、带宽等

水平扩容:将任务分配到多台计算机上

2. MongoDB分片集群架构

MongoDB分片集群(Sharded Cluster)是对数据进行水平扩展的一种方式。MongoDB使用分片集群来支持大数据集和高吞吐量的业务场景。在分片模式下,存储不同的切片数据的节点被称为分片节点,一个分片集群内包含了多个分片节点。当然,除了分片节点,集群中还需要一些配置节点、路由节点,以保证分片机制的正常运作。

核心概念

数据分片:分片用于存储真正的数据,并提供最终的数据读写访问。分片仅仅是一个逻辑的概念,它可以是一个单独的mongod实例,也可以是一个复制集。图中的Shard1、Shard2都是一个复制集分片。在生产环境中也一般会使用复制集的方式,这是为了防止数据节点出现单点故障。

配置服务器(Config Server):配置服务器包含多个节点,并组成一个复制集结构,对应于图中的ConfigRepISet。配置复制集中保存了整个分片集群中的元数据,其中包含各个集合的分片策略,以及分片的路由表等。如果我们查询一个数据,到底在哪个Shard里面,就是通过这个配置知道的。

查询路由(mongos) : mongos是分片集群的访问入口,其本身并不持久化数据。mongos启动后,会从配置服务器中加载元数据。之后mongos开始提供访问服务,并将用户的请求正确路由到对应的分片。在分片集群中可以部署多个mongos以分担客户端请求的压力。

软件部署

在官网找到适合amazon linux2的yum源,官网地址https://www.mongodb.com/docs/manual/administration/install-enterprise-linux/

#在amazon linux2部署,添加yum源,MongoDB.repo
[mongodb-enterprise-7.0]
name=MongoDB Enterprise Repository
baseurl=https://repo.mongodb.com/yum/amazon/2/mongodb-enterprise/7.0/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc

安装MongoDB最新版↓

yum -y install mongodb-org

下载指定版本需要指定所有组件为同版本↓

yum install -y mongodb-enterprise-7.0.6 mongodb-enterprise-database-7.0.6 mongodb-enterprise-server-7.0.6 mongodb-mongosh-7.0.6 mongodb-enterprise-mongos-7.0.6 mongodb-enterprise-tools-7.0.6

防止意外升级,请通过将以下exclude指令添加到 /etc/yum.conf文件中来固定程序包

exclude=mongodb-enterprise,mongodb-enterprise-database,mongodb-enterprise-server,mongodb-enterprise-shell,mongodb-enterprise-mongos,mongodb-enterprise-tools

部署分片集群

Deploy a Sharded Cluster — MongoDB Manual

主机名和配置

一般是多台服务器分别启动多个MongoDB实例,我这里部署使用的单ec2启动一个MongoDB,准备了一共12台作为一个3分片MongoDB集群,每个分片包含1主2从,另外三台作为config-server+route,配置服务器和路由服务器使用,本地部署或者测试可以在hosts配置解析,作为ip的代替,开始前注意所有机器直接的连接畅通,防止集群部署出现问题

创建 Config Server 副本集

对于生产部署,最少副本集内包含3名成员,出于测试目的可以只有一名成员,这个副本集内的机器全都作为Config Server(配置服务器)

通过配置文件或者命令行启动三台MongoDB

配置文件
systemLog:
  destination: file #指定日志输出目标为文件
  logAppend: true #日志文件的末尾追加新的日志条目
  path: /data/config/log/config.log #指定日志文件的路径
storage:
  dbPath: /data/config/db #指定 MongoDB 数据文件的存储路径
processManagement:
  timeZoneInfo: /usr/share/zoneinfo #指定时区信息文件的路径
net:
  port: 27019 #指定MongoDB服务器监听的端口号,不写默认见监听27019
  bindIp: 0.0.0.0   #指定 MongoDB监听的IP地址,0.0.0.0所有ipv4都可以登陆
replication:
  replSetName: config  #设置当前节点所属的复制集的名称,集群内不可重复
sharding:
  clusterRole: configsvr #设置当前节点的角色为配置服务器

mongod -f /配置文件路径 --fork 

执行命令启动MongoDB服务器,--fork是在后台运行

命令行启动
mongod --bind_ip 0.0.0.0 --replSet 集群名称 --dbpath 数据存放路径\
--logpath 日志路径/mongod.log --port 监听端口 --fork \
--configsvr #集群角色 

使用命令行最好将启动命令记录下来,数据库关闭后再启动用同样的命令

启动3台服务器后,通过MongoDB的shell进入其中任意一台,执行命令来创建副本集

mongosh ip:端口 进入


rs.initiate(
  {
    _id: "config副本集的名字", 
    configsvr: true,
    members: [
      { _id : 0, host : "ip1:27019" },
      { _id : 1, host : "ip2:27019" },
      { _id : 2, host : "ip3:27019" }
    ]
  }
)

在shell内执行命令来初始化副本集

输入rs.status可以查看到副本集状态

创建shard副本集,作为分片

对于生产部署,请使用至少具有三个副本集的副本集成员。出于测试目的,可以创建单成员副本设置。

配置文件启动

systemLog:
  destination: file
  logAppend: true
  path: /data/log/mongo.log
storage:
  dbPath: /data/db
processManagement:
  timeZoneInfo: /usr/share/zoneinfo
net:
  port: 27018 #监听端口,不设置则默认27018
  bindIp: 0.0.0.0
replication:
  replSetName: shard #分片名字,集群内唯一
sharding:
  clusterRole: shardsvr #作为分片服务器的身份启动
mongod -f /配置文件路径 --fork 

命令行启动

mongod --bind_ip 0.0.0.0 --replSet 集群名称 --dbpath 数据存放路径  \
--logpath 日志存放路径/mongod.log --port 端口 --fork \
--shardsvr #分片集群的身份

启动后通过mongosh登陆其中任意一台shell,执行命令来初始化副本集

rs.initiate(
  {
    _id : "集群名称",
    members: [
      { _id : 0, host : "ip1:27018" },
      { _id : 1, host : "ip2:27018" },
      { _id : 2, host : "ip3:27018" }
    ]
  }
)

执行成功后可以rs.status

为分片集群启动mongos

启动mongos(集群路由)需要先配置好config server副本集

配置文件启动

systemLog:
  destination: file
  logAppend: true
  path: /data/mongos/mongos.log #日志路径
net:
  port: 27017 #不设置默认27017
  bindIp: 0.0.0.0
sharding:
  configDB: config/ip1:27019,ip2:27019,ip3:27019
#添加config server副本集的集群名称和ip端口                

命令行启动

mongos --bind_ip 0.0.0.0 --logpath /data/mongos/mongos.log --port 27017 --fork \
--configdb config副本集名称/config-ip1:27019,config-ip2:27019,config-ip3:27019

启动完成后使用mongosh连接到路由服务器中任意一台的mongos,进行添加分片

sh.addShard("shard1名称/ip1:27018,ip2:27018,ip3:27018")

执行sh.status()可以查看分片信息

之后初始化完成的其他分片,在mongos路由服务器使用同样的命令就可以添加到集群,整个集群的读写操作都是从mongos路由服务器来进行转发的

进行写入数据测试

#插入测试数据
 use company
for (var i = 0; i < 10000; i++) {
    db.emp.insert({i: i});
}
#为集合创建索引
db.emp.createIndex({ i: 1 })
#启用集合分片
sh.shardCollection("company.emp", { i: 1 })
<p>#查询数据分布
db.emp.getShardDistribution()

正常关闭数据库命令,需要切换到admin库

use admin
db.shutdownServer()

当 MongoDB 正常关闭时,mongod.lock 文件会被删除。但如果 MongoDB 异常关闭(如非正常停机、服务器崩溃等),这个文件可能会残留在数据目录中。在重新启动 MongoDB 之前,您可以手动删除这个文件,以确保 MongoDB 能够正常启动。