MongoDB复制集 #

一、复制集概述 #

1.1 什么是复制集 #

复制集(Replica Set)是一组MongoDB实例,维护相同的数据集,提供数据冗余和高可用性。

text
复制集架构
┌─────────────────────────────────────┐
│         Primary (主节点)            │
│         读写操作                    │
└──────────────┬──────────────────────┘
               │ 复制
       ┌───────┴───────┐
       ▼               ▼
┌─────────────┐ ┌─────────────┐
│ Secondary   │ │ Secondary   │
│ (从节点)    │ │ (从节点)    │
│ 只读        │ │ 只读        │
└─────────────┘ └─────────────┘

1.2 复制集特点 #

特点 说明
自动故障转移 主节点故障时自动选举新主节点
数据冗余 多个节点保存相同数据
读写分离 读操作可以分散到从节点
高可用性 单节点故障不影响服务

1.3 复制集成员 #

成员类型 说明
Primary 主节点,处理所有写操作
Secondary 从节点,复制主节点数据
Arbiter 仲裁节点,参与选举但不存储数据
Hidden 隐藏节点,对客户端不可见
Delayed 延迟节点,延迟复制数据

二、复制集配置 #

2.1 创建复制集 #

javascript
// 1. 启动MongoDB实例(配置文件)
// mongod.conf
replication:
  replSetName: rs0
  oplogSizeMB: 1024

// 2. 启动实例
mongod -f /etc/mongod.conf

// 3. 初始化复制集
rs.initiate({
    _id: "rs0",
    members: [
        { _id: 0, host: "mongodb1:27017" },
        { _id: 1, host: "mongodb2:27017" },
        { _id: 2, host: "mongodb3:27017" }
    ]
})

2.2 查看复制集状态 #

javascript
// 查看复制集状态
rs.status()

// 输出示例
{
    set: 'rs0',
    date: ISODate("..."),
    myState: 1,
    members: [
        {
            _id: 0,
            name: 'mongodb1:27017',
            health: 1,
            state: 1,
            stateStr: 'PRIMARY',
            ...
        },
        {
            _id: 1,
            name: 'mongodb2:27017',
            health: 1,
            state: 2,
            stateStr: 'SECONDARY',
            ...
        }
    ],
    ok: 1
}

2.3 查看复制集配置 #

javascript
// 查看复制集配置
rs.conf()

// 输出示例
{
    _id: 'rs0',
    version: 1,
    members: [
        {
            _id: 0,
            host: 'mongodb1:27017',
            arbiterOnly: false,
            hidden: false,
            priority: 1,
            ...
        }
    ],
    settings: { ... }
}

三、复制集管理 #

3.1 添加成员 #

javascript
// 添加从节点
rs.add("mongodb4:27017")

// 添加仲裁节点
rs.addArb("mongodb5:27017")

// 添加带配置的成员
rs.add({
    host: "mongodb4:27017",
    priority: 1,
    hidden: false
})

3.2 删除成员 #

javascript
// 删除成员
rs.remove("mongodb4:27017")

3.3 修改成员配置 #

javascript
// 修改成员配置
const config = rs.conf()
config.members[1].priority = 2
config.members[1].hidden = false
rs.reconfig(config)

3.4 强制重新配置 #

javascript
// 强制重新配置(当大多数节点不可用时)
const config = rs.conf()
config.version++
rs.reconfig(config, { force: true })

四、成员类型配置 #

4.1 仲裁节点 #

javascript
// 添加仲裁节点
rs.addArb("mongodb5:27017")

// 或
rs.add({
    host: "mongodb5:27017",
    arbiterOnly: true
})

4.2 隐藏节点 #

javascript
// 配置隐藏节点
const config = rs.conf()
config.members[2].hidden = true
config.members[2].priority = 0
rs.reconfig(config)

4.3 延迟节点 #

javascript
// 配置延迟节点
const config = rs.conf()
config.members[2].hidden = true
config.members[2].priority = 0
config.members[2].slaveDelay = 3600  // 延迟1小时
rs.reconfig(config)

4.4 优先级配置 #

javascript
// 配置优先级
const config = rs.conf()
config.members[0].priority = 2  // 更可能成为主节点
config.members[1].priority = 1
config.members[2].priority = 0  // 永远不会成为主节点
rs.reconfig(config)

五、故障转移 #

5.1 自动故障转移 #

text
故障转移流程
┌─────────────────────────────────────┐
│  Primary故障                        │
│    ↓                                │
│  Secondary检测到Primary不可用       │
│    ↓                                │
│  发起选举                           │
│    ↓                                │
│  获得多数票的Secondary成为Primary   │
│    ↓                                │
│  其他Secondary同步新Primary         │
└─────────────────────────────────────┘

5.2 手动降级 #

javascript
// 主节点降级为从节点
rs.stepDown()

// 指定降级时间(秒)
rs.stepDown(60)

5.3 冻结节点 #

javascript
// 冻结节点(不参与选举)
rs.freeze(120)  // 冻结120秒

// 解冻
rs.freeze(0)

5.4 强制选举 #

javascript
// 强制重新选举
rs.stepDown()
// 或
rs.reconfigForReconfigSet()

六、读写分离 #

6.1 读偏好设置 #

读偏好 说明
primary 只从主节点读取(默认)
primaryPreferred 优先主节点,不可用时读从节点
secondary 只从从节点读取
secondaryPreferred 优先从节点,不可用时读主节点
nearest 从网络延迟最低的节点读取

6.2 连接时设置读偏好 #

javascript
// 连接字符串设置读偏好
mongodb://host1,host2,host3/db?readPreference=secondary

// 客户端设置读偏好
db.getMongo().setReadPref("secondary")

// 查询时设置读偏好
db.users.find().readPref("secondary")

6.3 读偏好标签 #

javascript
// 配置节点标签
const config = rs.conf()
config.members[0].tags = { dc: "east", use: "reporting" }
config.members[1].tags = { dc: "west", use: "reporting" }
rs.reconfig(config)

// 使用标签读取
db.users.find().readPref("secondary", [{ dc: "east" }])

七、Oplog #

7.1 Oplog概述 #

Oplog(Operations Log)是复制集的操作日志,记录所有写操作。

javascript
// 查看oplog
db.getSiblingDB("local").oplog.rs.find().limit(10)

// oplog结构
{
    ts: Timestamp(1234567890, 1),  // 时间戳
    h: NumberLong("..."),          // 哈希值
    v: 2,                          // 版本
    op: "i",                       // 操作类型
    ns: "mydb.users",              // 命名空间
    o: { ... }                     // 操作文档
}

7.2 Oplog操作类型 #

操作类型 说明
i insert
u update
d delete
c command
n no-op

7.3 Oplog大小 #

javascript
// 查看oplog大小
db.getSiblingDB("local").oplog.rs.stats()

// 修改oplog大小(MongoDB 4.0+)
db.adminCommand({
    replSetResizeOplog: 1,
    size: 2048  // MB
})

八、复制集监控 #

8.1 复制延迟 #

javascript
// 查看复制延迟
rs.printSlaveReplicationInfo()

// 输出示例
source: mongodb2:27017
    syncedTo: Mon Jan 01 2024 12:00:00 GMT+0800
    0 secs (0 hrs) behind the primary
source: mongodb3:27017
    syncedTo: Mon Jan 01 2024 11:59:50 GMT+0800
    10 secs (0 hrs) behind the primary

8.2 复制集状态 #

javascript
// 查看复制集状态
rs.status()

// 检查成员健康状态
rs.status().members.forEach(member => {
    print(`${member.name}: ${member.health === 1 ? '健康' : '异常'}`)
})

8.3 选举统计 #

javascript
// 查看选举统计
db.serverStatus().elections

九、最佳实践 #

9.1 复制集部署建议 #

text
推荐架构
┌─────────────────────────────────────┐
│         Primary                     │
│         (数据中心A)                 │
└──────────────┬──────────────────────┘
               │
       ┌───────┴───────┐
       ▼               ▼
┌─────────────┐ ┌─────────────┐
│ Secondary   │ │ Secondary   │
│ (数据中心B) │ │ (数据中心C) │
└─────────────┘ └─────────────┘

建议:
1. 至少3个节点(1主2从)
2. 跨机房部署提高可用性
3. 奇数个投票成员
4. 使用仲裁节点节省资源

9.2 网络配置 #

javascript
// 配置bindIp
net:
  bindIp: 0.0.0.0  // 允许所有IP连接

// 配置副本集名称
replication:
  replSetName: rs0

9.3 安全配置 #

javascript
// 启用认证
security:
  authorization: enabled
  keyFile: /etc/mongodb/keyfile

// 创建管理员
use admin
db.createUser({
    user: "admin",
    pwd: "password",
    roles: ["root"]
})

十、总结 #

复制集操作速查表:

操作 命令
初始化复制集 rs.initiate()
查看状态 rs.status()
查看配置 rs.conf()
添加成员 rs.add()
删除成员 rs.remove()
重新配置 rs.reconfig()
主节点降级 rs.stepDown()
冻结节点 rs.freeze()

读偏好选项:

选项 说明
primary 只读主节点
primaryPreferred 优先主节点
secondary 只读从节点
secondaryPreferred 优先从节点
nearest 最近节点

下一步,让我们学习分片!

最后更新:2026-03-27