MongoDB 复制集实战
MongoDB 复制集架构

一、复制集核心原理
主从架构与数据冗余
-
复制集由**主节点(Primary)和多个从节点(Secondary)**构成,所有节点存储相同数据集副本。
-
主节点:唯一接受写操作的节点,通过操作日志(oplog)记录所有数据变更。
-
从节点:异步拉取主节点的 oplog 并重放,实现数据同步,确保最终一致性。
自动故障转移(Failover)
-
当主节点不可达(心跳超时),从节点通过 Raft 选举协议发起投票,选出新主节点。
-
触发条件:主节点宕机、网络分区、手动维护等。
-
选举依据:节点优先级、数据最新性(最新 oplog 时间戳)。
数据同步机制
-
主节点所有写操作按顺序记录在 local.oplog.rs 集合,类似事务日志。
-
从节点持续拉取并应用 oplog,确保数据一致性。
读写分离与一致性
-
写操作:仅主节点处理,支持 Write Concern 配置写确认级别(如多数节点确认)。
-
读操作:默认从主节点读取,可通过 Read Preference 配置从从节点读取(可能读到旧数据)。
复制集架构组成
角色 | 职责 | 特点 |
---|---|---|
Primary | 处理所有写操作,记录 oplog | 唯一可写节点 |
Secondary | 同步主节点数据,可提供读服务 | 可配置为隐藏节点、延迟节点 |
Arbiter(仲裁节点) | 仅参与选举投票,不存储数据 | 节省资源,避免偶数节点导致选举僵局 |
|
最小部署要求
-
至少 3 个节点(推荐 1 主 + 2 从,或 1 主 + 1 从 + 1 仲裁)。
-
奇数节点总数,避免选举票数平局。
数据同步流程
graph LR
Primary -->|写入数据| Oplog
Oplog -->|异步推送| Secondary1
Oplog -->|异步推送| Secondary2
Secondary1 -->|重放oplog| 数据副本
Secondary2 -->|重放oplog| 数据副本
心跳与选举机制
-
节点间每 2 秒发送心跳包检测存活状态。
-
主节点失联超过 10 秒(默认),触发选举流程。
投票规则:节点优先级高的优先当选。数据最新的节点(oplog 最新)优先。
MongoDB 复制集实现
环境确认
OS | IP | Role | Port |
---|---|---|---|
rocky8 | 192.168.80.44 | primary | 27017 |
rocky8 | 192.168.80.55 | secondary | 27017 |
rocky8 | 192.168.80.66 | secondary | 27017 |
[ ] |
首先修改配置文件添加复制集名称:
replication:
replSetName: "mogorepl" # 替换为你的复制集名称

每个节点都执行:
config = { _id: 'mogorepl', members: [
{_id: 0, host: '192.168.80.44:27017'},
{_id: 1, host: '192.168.80.55:27017'} ,
{_id: 2, host: '192.168.80.66:27017'}]
}

确认集群状态

验证数据是否同步
主节点:
use testdb
db.products.insertOne({
name: "Laptop",
price: 999.99,
stock: 50
})

从节点查看数据:
rs.secondaryOk()
use testdb
db.products.find().pretty()

MongoDB 复制集基本运维
添加和删除节点
rs.remove("192.168.80.66:27017");
rs.add("192.168.80.66:27017");

修改配置为一主一从一仲裁
config = { _id: 'mogorepl', members: [
{_id: 0, host: '192.168.80.44:27017'},
{_id: 1, host: '192.168.80.55:27017'} ,
{_id: 2, host: '192.168.80.66:27017', "arbiterOnly": true}]
}
rs.initiate(config)


特殊从节点配置
# 在主节点执行下面操作配置特殊节点并保存
config = rs.conf()
config.members[3].hidden = true
config.members[3].priority = 0
config.members[3].arbiterOnly = true # 修正拼写:arbitterOnly → arbiterOnly
config.members[3].slaveDelay = 120
config.members[3].votes = 0
rs.reconfig(config)
# 取消以上配置
config = rs.conf()
config.members[3].priority = 1
config.members[3].hidden = false # 修正布尔值:False → false
config.members[3].slaveDelay = 0
config.members[3].votes = 1
rs.reconfig(config)
# 配置成功后,通过以下命令查询配置后的属性
rs.conf()
# 定义变量说明
# - hidden:表示某个成员是否隐藏(从0开始表示第i个成员,顺序与 rs.conf() 显示一致,非 _id 值)
# - priority=0:表示不参与主节点选举,但默认仍可投票(需配合 votes=0 完全禁用投票)
# - arbiterOnly:将节点配置为仲裁节点(不存储数据,仅参与投票)
# - slaveDelay:以秒为单位的延迟复制时间(生产环境建议设置为 10800-21600 秒,即 3-6 小时)
# - votes=0:表示该节点不参与投票
# 加载配置需通过 rs.reconfig(config) 生效