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

MongoDB创建副本集步骤与注意事项

2021-08-052.9k 阅读

MongoDB 副本集概述

MongoDB 副本集是一组维护相同数据集的 MongoDB 实例。副本集提供数据冗余、高可用性和读扩展功能。在副本集中,有一个主节点(Primary)负责处理所有写入操作,多个从节点(Secondary)从主节点复制数据。如果主节点出现故障,副本集可以自动选举一个从节点成为新的主节点,确保服务的连续性。

环境准备

在开始创建副本集之前,需要准备以下环境:

  1. 安装 MongoDB:确保在所有参与副本集的服务器上安装了 MongoDB。可以从 MongoDB 官方网站下载适合你操作系统的安装包进行安装。
  2. 配置网络:确保所有服务器之间可以相互通信,并且防火墙配置允许 MongoDB 使用的端口(默认为 27017)进行通信。
  3. 创建数据目录:为每个 MongoDB 实例创建独立的数据目录。例如,在每个服务器上创建 /data/db1/data/db2/data/db3 等目录用于存储不同实例的数据。

创建副本集步骤

1. 配置 MongoDB 实例

为每个 MongoDB 实例创建配置文件。以三个节点的副本集为例,假设三个服务器的 IP 分别为 192.168.1.100192.168.1.101192.168.1.102

  • 第一个节点(192.168.1.100)的配置文件(mongod1.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod1.log
  logAppend: true
storage:
  dbPath: /data/db1
  journal:
    enabled: true
net:
  bindIp: 192.168.1.100
  port: 27017
replication:
  oplogSizeMB: 1024
  replSetName: rs0
  • 第二个节点(192.168.1.101)的配置文件(mongod2.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod2.log
  logAppend: true
storage:
  dbPath: /data/db2
  journal:
    enabled: true
net:
  bindIp: 192.168.1.101
  port: 27017
replication:
  oplogSizeMB: 1024
  replSetName: rs0
  • 第三个节点(192.168.1.102)的配置文件(mongod3.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod3.log
  logAppend: true
storage:
  dbPath: /data/db3
  journal:
    enabled: true
net:
  bindIp: 192.168.1.102
  port: 27017
replication:
  oplogSizeMB: 1024
  replSetName: rs0

上述配置文件中,systemLog 部分配置日志相关信息,storage 部分指定数据存储路径,net 部分配置绑定的 IP 和端口,replication 部分指定副本集名称和操作日志大小。

2. 启动 MongoDB 实例

在每个服务器上分别启动 MongoDB 实例。

  • 192.168.1.100 上启动:
mongod -f /etc/mongod1.conf
  • 192.168.1.101 上启动:
mongod -f /etc/mongod2.conf
  • 192.168.1.102 上启动:
mongod -f /etc/mongod3.conf

3. 初始化副本集

连接到其中一个 MongoDB 实例,通常是第一个节点,进行副本集初始化。

mongo --host 192.168.1.100 --port 27017

在 MongoDB shell 中执行以下命令初始化副本集:

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "192.168.1.100:27017" },
    { _id: 1, host: "192.168.1.101:27017" },
    { _id: 2, host: "192.168.1.102:27017" }
  ]
})

上述命令中,_id 是副本集的名称,与配置文件中的 replSetName 一致,members 数组列出了副本集中所有成员的主机和端口。

4. 验证副本集状态

初始化完成后,可以使用 rs.status() 命令查看副本集状态。

rs.status()

该命令会返回副本集的详细状态信息,包括主节点、从节点的状态,同步进度等。例如,正常情况下会看到类似以下信息:

{
  "set" : "rs0",
  "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" : 3,
  "optimes" : {
    "lastCommittedOpTime" : {
      "ts" : Timestamp(1672536000, 1),
      "t" : NumberLong(1)
    },
    "lastCommittedWallTime" : ISODate("2024-01-01T12:00:00Z"),
    "readConcernMajorityOpTime" : {
      "ts" : Timestamp(1672536000, 1),
      "t" : NumberLong(1)
    },
    "readConcernMajorityWallTime" : ISODate("2024-01-01T12:00:00Z"),
    "appliedOpTime" : {
      "ts" : Timestamp(1672536000, 1),
      "t" : NumberLong(1)
    },
    "durableOpTime" : {
      "ts" : Timestamp(1672536000, 1),
      "t" : NumberLong(1)
    },
    "lastAppliedWallTime" : ISODate("2024-01-01T12:00:00Z"),
    "lastDurableWallTime" : ISODate("2024-01-01T12:00:00Z")
  },
  "members" : [
    {
      "_id" : 0,
      "name" : "192.168.1.100:27017",
      "health" : 1,
      "state" : 1,
      "stateStr" : "PRIMARY",
      "uptime" : 120,
      "optime" : {
        "ts" : Timestamp(1672536000, 1),
        "t" : NumberLong(1)
      },
      "optimeDate" : ISODate("2024-01-01T12:00:00Z"),
      "syncingTo" : "",
      "syncSourceHost" : "",
      "syncSourceId" : -1,
      "infoMessage" : "",
      "electionTime" : Timestamp(1672535880, 2),
      "electionDate" : ISODate("2024-01-01T11:58:00Z"),
      "configVersion" : 1,
      "self" : true,
      "lastHeartbeatMessage" : ""
    },
    {
      "_id" : 1,
      "name" : "192.168.1.101:27017",
      "health" : 1,
      "state" : 2,
      "stateStr" : "SECONDARY",
      "uptime" : 118,
      "optime" : {
        "ts" : Timestamp(1672536000, 1),
        "t" : NumberLong(1)
      },
      "optimeDate" : ISODate("2024-01-01T12:00:00Z"),
      "syncingTo" : "192.168.1.100:27017",
      "syncSourceHost" : "192.168.1.100:27017",
      "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" : "192.168.1.102:27017",
      "health" : 1,
      "state" : 2,
      "stateStr" : "SECONDARY",
      "uptime" : 116,
      "optime" : {
        "ts" : Timestamp(1672536000, 1),
        "t" : NumberLong(1)
      },
      "optimeDate" : ISODate("2024-01-01T12:00:00Z"),
      "syncingTo" : "192.168.1.100:27017",
      "syncSourceHost" : "192.168.1.100:27017",
      "syncSourceId" : 0,
      "infoMessage" : "",
      "configVersion" : 1,
      "lastHeartbeat" : ISODate("2024-01-01T12:00:00Z"),
      "lastHeartbeatRecv" : ISODate("2024-01-01T12:00:00Z"),
      "pingMs" : NumberLong(0),
      "lastHeartbeatMessage" : ""
    }
  ],
  "ok" : 1
}

其中,myState 为 1 表示当前节点是主节点,stateStrPRIMARY 也表示主节点,SECONDARY 表示从节点。

注意事项

1. 网络问题

  • 网络延迟:副本集成员之间的网络延迟应尽量低。高延迟可能导致数据同步缓慢,影响副本集的性能和可用性。可以使用 ping 命令和网络测试工具(如 iperf)来检查网络延迟和带宽。
  • 网络分区:网络分区是指副本集成员之间的网络连接出现中断,导致部分成员无法相互通信。MongoDB 副本集通过选举机制来处理网络分区情况,但在网络分区期间,可能会出现数据不一致的情况。为了避免网络分区,建议使用可靠的网络设备和冗余网络连接。

2. 数据同步

  • 初始同步:当新节点加入副本集或从节点重新启动时,会进行初始同步。初始同步过程中,从节点会从主节点复制整个数据集,这可能会消耗大量的网络带宽和磁盘 I/O。可以通过合理安排初始同步时间(如在业务低峰期进行),或者使用预初始化数据文件(--replSetInitialSync 选项)来减少对业务的影响。
  • 同步延迟:从节点可能会因为各种原因(如网络问题、磁盘 I/O 瓶颈等)导致同步延迟。可以通过 rs.status() 命令中的 optime 字段来检查从节点与主节点的数据同步情况。如果同步延迟较大,需要排查原因并解决。

3. 选举机制

  • 选举条件:MongoDB 副本集的选举机制遵循一定的规则。主节点故障后,副本集内的从节点会发起选举,选举出一个新的主节点。选举条件包括节点的优先级(priority)、节点的日志是否最新等。优先级默认值为 1,取值范围为 0 到 1000。优先级为 0 的节点不会参与选举成为主节点。
  • 选举时间:选举过程通常需要几秒钟到几十秒钟不等。在选举期间,副本集可能无法处理写入操作,因此应用程序需要能够处理短暂的不可用情况。

4. 副本集配置

  • 成员数量:副本集成员数量建议为奇数个,因为奇数个成员可以在出现网络分区时,保证多数节点能够达成一致,从而选举出新的主节点。例如,三个节点的副本集可以容忍一个节点故障;五个节点的副本集可以容忍两个节点故障。
  • 仲裁节点:仲裁节点(Arbiter)是一种特殊的副本集成员,它不存储数据,只参与选举。仲裁节点可以在不增加数据存储和网络负载的情况下,增加副本集的投票数。例如,在两个数据节点的副本集中添加一个仲裁节点,可以使副本集能够在一个数据节点故障时正常工作。仲裁节点的配置与普通节点类似,只需在配置文件中设置 arbiterOnly: true
systemLog:
  destination: file
  path: /var/log/mongodb/arbiter.log
  logAppend: true
net:
  bindIp: 192.168.1.103
  port: 27017
replication:
  replSetName: rs0
  arbiterOnly: true

5. 安全配置

  • 身份验证:为了保证副本集的安全性,应启用身份验证。可以在 MongoDB 配置文件中添加 security.authorization: enabled 来启用身份验证。然后使用 mongo 命令行工具创建用户,并使用 db.auth() 方法进行身份验证。
// 创建用户
use admin
db.createUser({
  user: "admin",
  pwd: "password",
  roles: [ { role: "root", db: "admin" } ]
})

// 身份验证
db.auth("admin", "password")
  • SSL/TLS 加密:可以通过配置 MongoDB 使用 SSL/TLS 加密来保护数据传输的安全性。在配置文件中添加以下配置:
net:
  ssl:
    mode: requireSSL
    PEMKeyFile: /path/to/your/key.pem
    CAFile: /path/to/your/ca.pem

上述配置中,mode 设置为 requireSSL 表示强制使用 SSL/TLS 加密,PEMKeyFile 指定服务器的私钥文件,CAFile 指定证书颁发机构的证书文件。

6. 监控与维护

  • 监控工具:使用 MongoDB 自带的监控工具(如 mongostatmongotop)以及第三方监控工具(如 Prometheus + Grafana)来监控副本集的性能指标,如 CPU 使用率、内存使用率、磁盘 I/O、网络流量等。
  • 定期维护:定期检查副本集的状态,包括成员的健康状况、数据同步情况等。定期清理 MongoDB 的日志文件和旧的操作日志,以避免磁盘空间耗尽。

通过以上步骤和注意事项,可以成功创建并维护一个稳定、高效的 MongoDB 副本集,为应用程序提供可靠的数据存储和高可用性保障。在实际应用中,需要根据业务需求和环境特点,合理调整副本集的配置和参数。