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