MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

轻松向 MongoDB 添加服务器的步骤

2022-12-316.5k 阅读

了解 MongoDB 服务器架构基础

在开始向 MongoDB 添加服务器之前,我们需要对 MongoDB 的服务器架构有一定的了解。MongoDB 是一个分布式文档数据库,它的架构设计旨在提供高可用性、可扩展性以及高性能。

副本集(Replica Sets)

副本集是 MongoDB 实现高可用性的核心机制之一。它由一组 MongoDB 服务器组成,其中包含一个主节点(Primary)和多个从节点(Secondary)。主节点负责处理所有的写操作,从节点则复制主节点的数据,并可以处理读操作。当主节点发生故障时,副本集内会自动进行选举,从从节点中选出一个新的主节点,以确保服务的连续性。

副本集的架构图如下:

graph TD;
    A[Primary] --> B[Secondary];
    A --> C[Secondary];
    A --> D[Arbiter];

在这个架构图中,Primary 是主节点,负责处理写操作和部分读操作。Secondary 是从节点,它们复制主节点的数据,并可以处理读操作。Arbiter 是仲裁节点,它不存储数据,主要用于在选举新主节点时参与投票。

分片集群(Sharded Clusters)

分片集群是 MongoDB 实现水平扩展的关键机制。当数据量和负载不断增长,单个服务器无法满足需求时,我们可以通过分片集群将数据分布在多个服务器上,从而提高系统的整体性能和存储能力。

分片集群主要由以下几个部分组成:

  1. 分片(Shards):实际存储数据的服务器,每个分片可以是一个单独的服务器,也可以是一个副本集。
  2. 配置服务器(Config Servers):存储分片集群的元数据,包括数据分布信息等。配置服务器通常以副本集的形式部署,以确保高可用性。
  3. 路由服务器(mongos):客户端连接到分片集群的入口,它负责接收客户端的请求,并根据配置服务器中的元数据将请求路由到相应的分片上。

分片集群的架构图如下:

graph TD;
    E[mongos] --> F[Config Server Replica Set];
    E --> G[Shard 1 Replica Set];
    E --> H[Shard 2 Replica Set];

在这个架构图中,mongos 是路由服务器,Config Server Replica Set 是配置服务器副本集,Shard 1 Replica Set 和 Shard 2 Replica Set 是两个分片副本集。

准备工作

在向 MongoDB 添加服务器之前,我们需要完成一些准备工作,以确保添加过程的顺利进行。

环境准备

  1. 操作系统:MongoDB 支持多种操作系统,包括 Linux、Windows 和 macOS 等。在生产环境中,建议使用 Linux 操作系统,因为它具有更好的性能和稳定性。
  2. 硬件资源:根据服务器的用途和预期负载,合理分配硬件资源。例如,如果是作为主节点,需要足够的内存和 CPU 资源来处理写操作;如果是作为从节点或仲裁节点,对硬件资源的要求相对较低。
  3. 网络配置:确保服务器之间的网络畅通,并且配置合适的防火墙规则,允许 MongoDB 服务器之间以及客户端与服务器之间的通信。

安装 MongoDB

  1. 下载 MongoDB 安装包:根据操作系统的类型和版本,从 MongoDB 官方网站(https://www.mongodb.com/try/download/community)下载相应的安装包。
  2. 安装 MongoDB:按照安装向导的提示进行安装。在 Linux 系统上,也可以通过包管理器(如 apt、yum 等)进行安装。例如,在 Ubuntu 系统上,可以使用以下命令安装 MongoDB:
wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
  1. 启动 MongoDB 服务:安装完成后,启动 MongoDB 服务。在 Linux 系统上,可以使用以下命令启动服务:
sudo systemctl start mongod

并设置开机自启:

sudo systemctl enable mongod

配置 MongoDB

  1. 修改配置文件:MongoDB 的配置文件通常位于 /etc/mongod.conf。打开配置文件,根据需求进行配置。例如,要启用副本集功能,需要在配置文件中添加以下内容:
replication:
  replSetName: <replicaSetName>

其中 <replicaSetName> 是你为副本集指定的名称。

  1. 修改网络绑定:默认情况下,MongoDB 只绑定到本地回环地址 127.0.0.1。如果需要允许远程连接,需要将 bindIp 参数修改为服务器的实际 IP 地址或 0.0.0.0(注意,绑定到 0.0.0.0 会使服务器暴露在公网上,存在安全风险,在生产环境中需要谨慎使用)。例如:
net:
  bindIp: 0.0.0.0
  1. 重启 MongoDB 服务:修改配置文件后,需要重启 MongoDB 服务使配置生效:
sudo systemctl restart mongod

向副本集添加服务器

初始化副本集

  1. 连接到主节点:使用 mongo 命令行工具连接到 MongoDB 主节点。例如:
mongo --host <primaryHost> --port <primaryPort>

其中 <primaryHost> 是主节点的主机名或 IP 地址,<primaryPort> 是主节点的端口号(默认为 27017)。

  1. 初始化副本集:在 MongoDB shell 中,使用 rs.initiate() 命令初始化副本集。例如:
rs.initiate({
  _id: "<replicaSetName>",
  members: [
    { _id: 0, host: "<primaryHost>:<primaryPort>" }
  ]
})

其中 <replicaSetName> 是副本集的名称,<primaryHost><primaryPort> 分别是主节点的主机名或 IP 地址以及端口号。

添加从节点

  1. 连接到主节点:确保已经连接到 MongoDB 主节点的 shell。

  2. 添加从节点:使用 rs.add() 命令添加从节点。例如,要添加一个从节点,其主机名为 <secondaryHost>,端口号为 <secondaryPort>,可以使用以下命令:

rs.add("<secondaryHost>:<secondaryPort>")

添加仲裁节点

  1. 连接到主节点:同样需要连接到 MongoDB 主节点的 shell。

  2. 添加仲裁节点:使用 rs.addArb() 命令添加仲裁节点。例如,要添加一个仲裁节点,其主机名为 <arbiterHost>,端口号为 <arbiterPort>,可以使用以下命令:

rs.addArb("<arbiterHost>:<arbiterPort>")

向分片集群添加服务器

添加分片

  1. 连接到 mongos:使用 mongo 命令行工具连接到 mongos 路由服务器。例如:
mongo --host <mongosHost> --port <mongosPort>

其中 <mongosHost> 是 mongos 服务器的主机名或 IP 地址,<mongosPort> 是 mongos 服务器的端口号(默认为 27017)。

  1. 添加分片:在 MongoDB shell 中,使用 sh.addShard() 命令添加分片。如果分片是一个副本集,可以使用以下命令:
sh.addShard("<replicaSetName>/<primaryHost>:<primaryPort>,<secondaryHost1>:<secondaryPort1>,<secondaryHost2>:<secondaryPort2>")

其中 <replicaSetName> 是副本集的名称,<primaryHost><primaryPort> 是副本集中主节点的主机名或 IP 地址以及端口号,<secondaryHost1><secondaryHost2> 等是副本集中从节点的主机名或 IP 地址,<secondaryPort1><secondaryPort2> 等是相应从节点的端口号。

添加配置服务器

  1. 启动配置服务器:在新的服务器上安装并启动 MongoDB 作为配置服务器。按照前面介绍的安装和配置步骤,将 MongoDB 配置为配置服务器,注意需要使用不同的端口号(默认为 27019)。

  2. 连接到 mongos:连接到 mongos 路由服务器的 shell。

  3. 添加配置服务器:使用 sh.addConfigServer() 命令添加配置服务器。例如:

sh.addConfigServer("<configServerHost1>:<configServerPort1>,<configServerHost2>:<configServerPort2>,<configServerHost3>:<configServerPort3>")

其中 <configServerHost1><configServerHost2><configServerHost3> 等是配置服务器的主机名或 IP 地址,<configServerPort1><configServerPort2><configServerPort3> 等是相应配置服务器的端口号。

验证服务器添加结果

副本集验证

  1. 连接到主节点:使用 mongo 命令行工具连接到 MongoDB 主节点的 shell。

  2. 查看副本集状态:使用 rs.status() 命令查看副本集的状态。在输出结果中,可以看到副本集的成员列表,包括主节点、从节点和仲裁节点的状态信息。例如:

rs.status()

输出结果类似如下:

{
  "set": "<replicaSetName>",
  "date": ISODate("2024-01-01T12:00:00Z"),
  "myState": 1,
  "term": NumberLong(1),
  "syncingTo": "",
  "syncSourceHost": "",
  "syncSourceId": -1,
  "heartbeatIntervalMillis": NumberLong(2000),
  "majorityVoteCount": 2,
  "writeMajorityCount": 2,
  "votingMembersCount": 3,
  "writableVotingMembersCount": 2,
  "optimes": {
    "lastCommittedOpTime": {
      "ts": Timestamp(1704043200, 1),
      "t": NumberLong(1)
    },
    "lastCommittedWallTime": ISODate("2024-01-01T12:00:00Z"),
    "readConcernMajorityOpTime": {
      "ts": Timestamp(1704043200, 1),
      "t": NumberLong(1)
    },
    "appliedOpTime": {
      "ts": Timestamp(1704043200, 1),
      "t": NumberLong(1)
    },
    "durableOpTime": {
      "ts": Timestamp(1704043200, 1),
      "t": NumberLong(1)
    },
    "lastAppliedWallTime": ISODate("2024-01-01T12:00:00Z"),
    "lastDurableWallTime": ISODate("2024-01-01T12:00:00Z")
  },
  "members": [
    {
      "_id": 0,
      "name": "<primaryHost>:<primaryPort>",
      "health": 1,
      "state": 1,
      "stateStr": "PRIMARY",
      "uptime": 120,
      "optime": {
        "ts": Timestamp(1704043200, 1),
        "t": NumberLong(1)
      },
      "optimeDate": ISODate("2024-01-01T12:00:00Z"),
      "syncingTo": "",
      "syncSourceHost": "",
      "syncSourceId": -1,
      "infoMessage": "",
      "electionTime": Timestamp(1704043100, 1),
      "electionDate": ISODate("2024-01-01T11:58:20Z"),
      "configVersion": 1,
      "self": true,
      "lastHeartbeatMessage": ""
    },
    {
      "_id": 1,
      "name": "<secondaryHost1>:<secondaryPort1>",
      "health": 1,
      "state": 2,
      "stateStr": "SECONDARY",
      "uptime": 110,
      "optime": {
        "ts": Timestamp(1704043200, 1),
        "t": NumberLong(1)
      },
      "optimeDate": ISODate("2024-01-01T12:00:00Z"),
      "syncingTo": "<primaryHost>:<primaryPort>",
      "syncSourceHost": "<primaryHost>:<primaryPort>",
      "syncSourceId": 0,
      "infoMessage": "",
      "configVersion": 1,
      "lastHeartbeat": ISODate("2024-01-01T12:00:00Z"),
      "lastHeartbeatRecv": ISODate("2024-01-01T12:00:00Z"),
      "pingMs": NumberLong(0),
      "lastHeartbeatMessage": ""
    },
    {
      "_id": 2,
      "name": "<arbiterHost>:<arbiterPort>",
      "health": 1,
      "state": 7,
      "stateStr": "ARBITER",
      "uptime": 100,
      "lastHeartbeat": ISODate("2024-01-01T12:00:00Z"),
      "lastHeartbeatRecv": ISODate("2024-01-01T12:00:00Z"),
      "pingMs": NumberLong(0),
      "lastHeartbeatMessage": "",
      "configVersion": 1
    }
  ],
  "ok": 1
}

在这个输出结果中,可以看到 members 数组中列出了副本集的所有成员,以及它们的状态信息。stateStr 字段显示了成员的状态,如 PRIMARY 表示主节点,SECONDARY 表示从节点,ARBITER 表示仲裁节点。

分片集群验证

  1. 连接到 mongos:使用 mongo 命令行工具连接到 mongos 路由服务器的 shell。

  2. 查看分片状态:使用 sh.status() 命令查看分片集群的状态。在输出结果中,可以看到分片的列表、配置服务器的信息以及数据分布情况等。例如:

sh.status()

输出结果类似如下:

--- Sharding Status ---
  sharding version: {
    "_id" : 1,
    "minCompatibleVersion" : 5,
    "currentVersion" : 6,
    "clusterId" : ObjectId("656c2f5e2e7f464b7c197d0a")
  }
  shards:
    {  "_id" : "shard0000",  "host" : "shard0000/<primaryHost>:<primaryPort>,<secondaryHost1>:<secondaryPort1>,<secondaryHost2>:<secondaryPort2>",  "state" : 1 }
    {  "_id" : "shard0001",  "host" : "shard0001/<primaryHost1>:<primaryPort1>,<secondaryHost3>:<secondaryPort3>,<secondaryHost4>:<secondaryPort4>",  "state" : 1 }
  active mongoses:
    "4.4.0" : 2
  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" : "admin",  "partitioned" : false,  "primary" : "config" }
    {  "_id" : "test",  "partitioned" : true,  "primary" : "shard0000" }
      test.foo
        shard key: { "x" : 1 }
        chunks:
          shard0000	1
          shard0001	1
        { "x" : { "$minKey" : 1 } } -->> { "x" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)

在这个输出结果中,shards 部分列出了所有的分片信息,包括分片的 _idhostdatabases 部分显示了数据库的分片情况,包括哪些数据库是分片的,以及每个集合的分片键和数据分布情况。

常见问题及解决方法

副本集添加节点失败

  1. 网络问题:检查服务器之间的网络连接是否正常,可以使用 ping 命令测试连通性。如果网络不通,需要检查防火墙规则、网络配置等。
  2. 配置问题:确保所有节点的副本集配置一致,包括 replSetName 等参数。如果配置不一致,可能导致节点无法加入副本集。
  3. 版本兼容性问题:确保所有节点的 MongoDB 版本兼容。不兼容的版本可能会导致各种问题,包括节点添加失败。

分片集群添加服务器失败

  1. 配置服务器问题:检查配置服务器的状态是否正常。可以使用 rs.status() 命令查看配置服务器副本集的状态。如果配置服务器出现故障,可能导致添加分片或配置服务器失败。
  2. mongos 配置问题:确保 mongos 的配置正确,包括与配置服务器和分片的连接信息。如果 mongos 无法正确连接到配置服务器或分片,添加操作将失败。
  3. 权限问题:确保连接到 mongos 的用户具有足够的权限来执行添加分片和配置服务器的操作。如果权限不足,操作将被拒绝。

性能优化与监控

性能优化

  1. 合理配置硬件资源:根据服务器的角色和负载,合理分配 CPU、内存、磁盘等硬件资源。例如,主节点需要更多的内存来处理写操作,从节点可以适当分配更多的 CPU 资源来处理读操作。
  2. 优化索引:为频繁查询的字段创建合适的索引,可以显著提高查询性能。使用 createIndex() 命令在集合上创建索引。例如:
db.collection.createIndex({ field1: 1, field2: -1 })

这个命令在 collection 集合上为 field1 字段创建升序索引,为 field2 字段创建降序索引。

  1. 调整副本集同步策略:可以通过调整副本集的同步延迟等参数,来平衡数据一致性和性能。例如,可以使用 rs.syncFrom() 命令手动指定从节点的同步源,以优化同步过程。

监控

  1. 使用 MongoDB 自带的监控工具:MongoDB 提供了一些自带的监控工具,如 mongostatmongotopmongostat 可以实时显示 MongoDB 服务器的状态信息,包括插入、查询、更新、删除等操作的速率。例如:
mongostat --host <host> --port <port>

mongotop 可以显示每个集合的读写操作时间,帮助找出性能瓶颈。例如:

mongotop --host <host> --port <port>
  1. 使用第三方监控工具:也可以使用一些第三方监控工具,如 Prometheus 和 Grafana,来对 MongoDB 进行更全面的监控。通过配置 MongoDB Exporter,可以将 MongoDB 的指标数据发送到 Prometheus,然后使用 Grafana 进行可视化展示。

安全注意事项

  1. 认证和授权:启用 MongoDB 的认证和授权功能,确保只有授权的用户可以访问数据库。可以通过在配置文件中添加 security.authorization: enabled 来启用授权,然后使用 db.createUser() 命令创建用户。
  2. 网络安全:合理配置防火墙规则,限制 MongoDB 服务器的网络访问。避免将 MongoDB 服务器暴露在公网上,如果必须暴露,需要采取额外的安全措施,如使用 SSL/TLS 加密通信。
  3. 数据备份:定期进行数据备份,以防止数据丢失。可以使用 mongodumpmongorestore 命令进行数据备份和恢复。例如,使用以下命令进行数据备份:
mongodump --host <host> --port <port> --username <username> --password <password> --out <backupPath>

然后使用以下命令进行数据恢复:

mongorestore --host <host> --port <port> --username <username> --password <password> <backupPath>

通过以上步骤,我们可以轻松地向 MongoDB 添加服务器,并进行相应的配置、验证、优化和监控。在实际操作过程中,需要根据具体的业务需求和环境进行合理的调整和优化。