MongoDB复制集ReplicaSet实现和管理
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.mongoDB复制集概述
1.什么是复制集
MongoDB像MySQL一样,支持类似的主从复制架构,但无法实现自动故障转移,所以官方推荐使用复制集。
MongoDB复制集是将数据同步存储在多台服务器,复制集提供了数据的冗余备份,并在多个服务器上存储数据副本,保证数据的安全性。
MongoDB的复制至少需要两个节点,其中一个主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点的数据。
主节点记录在其上的所有oplog,从节点定期轮训主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
客户端写入数据到主节点时,主节点与从节点进行数据交互保证数据的一致性。
复制集的功能:
- 1.数据的高可用性;
- 2.异地容灾;
- 3.无需停机维护,如备份,重建索引,压缩等;
- 4.分布式读取数据,读操作的负载均衡;
2.复制集架构
参考链接:
https://www.mongodb.com/zh-cn/docs/manual/core/replica-set-architecture-three-members/
https://www.mongodb.com/zh-cn/docs/manual/core/replica-set-architectures/
https://www.mongodb.com/zh-cn/docs/manual/reference/mongodb-defaults/#std-label-default-wc-formula
复制集特征:
- N各技术节点的集群,一个副本集最多可以有50个节点;
- 基于选举机制,但只有7个投票节点,任何节点可作为主节点;
- 所有写入操作都在主节点,所以增加节点不会提供系统写性能,可以提升读性能;
- 主节点故障时,会自动选举出新节点替代,以实现故障转移;
多个节点数据同步的实现:
- 当一个修改操作,无论是插入,更新或者删除,到达主节点时,它对数据的操作将被记录下来,这些记录称为oplog;
- 从节点通过在主节点打开一个tailable游标不断获取新进主节点的oplog,并在自己的数据上回放,以此保持跟主节点的数据一致;
节点数量 | 选举新主节点所需的多数票 | 容错 |
---|---|---|
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
3.复制集角色说明
角色 | 作用 |
---|---|
Primary | 主节点,负责处理客户端请求,并将写请求记录在oplog。 |
Secondary | 从节点,负责从主节点同步数据,可以负责数据的读取的负载均衡 当主节点挂掉后,secondary可以接管从而变为Primary节点。 |
Arbiter | 仲裁节点只能参与投票,不能成为Primary,并且不从Primary同步数据。 当复制集为偶数时,最好加入一个Arbiter节点,以提升复制集的可用性。 比如你部署了2个节点的复制集,1个primary,1个Secondary,任意接地那党纪,复制集将不能提供服务,因为无法选举出Primary,这时可以给复制集添加一个Arbiter节点,即使有节点宕机仍能选出Primary节点。 |
Priority0 | Priority0节点的选举优先级为0,不能被选举为Primary,但可以从主节点同步数据和参与主节点选举时投票。 |
Vote0 | MongoDB3.0里,复制集成员最多50个,参与Primary选举投票的成员最多7个,其他成员的vote属性必须设置为0,即不参与投票。 |
Hidden | Hidden节点不能被选举为主节点,即Priority必须为0,并且对应用不可见。 因Hidden节点不会接受Driver的请求,可使用Hidden节点做一些数据备份,离线计算的任务,不会影响复制集的服务。 |
Delayed | Delayed节点必须是Hidden节点,并且其数据落后与Primary一段时间(可自行配置,比如落后1h) 因Delayed节点的数据比Primary落后一段时间,当错误或者无效的数据写入Primary时,可通过Delayed节点的数据来恢复到之前的时间点。 |
如上表所示,表示的是各种角色的作用,生产环境中,通常情况下是Primary和Secondary结合使用的场景较多。
默认情况下,应用程序将其读取操作指向复制集的主节点(即读取首选项模式'Primary'),但是,客户端可以通过read preference模式指定读取操作发送给到从节点。如下表所示,介绍了read preference模式,
参考链接:
https://www.mongodb.com/zh-cn/docs/manual/core/read-preference/#read-preference-modes
读取偏好模式 | 说明 |
---|---|
primary |
默认模式。从当前副本集主节点读取的所有操作。包含读操作的分布式事务必须使用读取偏好 primary 。给定事务中的所有操作必须路由至同一节点。 |
primaryPreferred |
在大多数情况下,操作将从主节点读取,但如果主节点不可用,则操作将从从节点成员读取。 |
secondary |
所有操作均会从副本集的辅助成员中读取。 |
secondaryPreferred |
操作通常从副本集的从节点成员读取数据。如果副本集只有一个主节点成员,并且没有其他成员,则操作将从主节点成员读取数据。 |
nearest |
根据指定的延迟阈值,从符合条件的随机副本集成员读取操作,无论该成员是主节点成员还是从节点成员。 该操作在计算延迟时会考虑以下因素:localThresholdMS 连接字符串选项maxStalenessSeconds 读取偏好选项任何指定的标签集列表 |
二.MongoDB一主两从架构实战
1.安装MongoDB基础环境
1.解压安装包
[root@node-exporter41 ~]# tar xf yinzhengjie-autoInstallMongoDB.tar.gz
[root@node-exporter42 ~]# tar xf yinzhengjie-autoInstallMongoDB.tar.gz
[root@node-exporter43 ~]# tar xf yinzhengjie-autoInstallMongoDB.tar.gz
2.安装MongoDB环境
[root@node-exporter41 ~]# ./install-mongodb.sh i
[root@node-exporter42 ~]# ./install-mongodb.sh i
[root@node-exporter43 ~]# ./install-mongodb.sh i
2.修改MongoDB的配置文件
1.修改MongoDB的配置文件
[root@node-exporter41 ~]# cat /yinzhengjie/softwares/mongodb/conf/mongo.conf
systemLog:
destination: file
path: "/yinzhengjie/softwares/mongodb/log/mongodb.log"
logAppend: true
storage:
dbPath: "/yinzhengjie/softwares/mongodb/data/"
journal:
commitIntervalMs: 100
processManagement:
fork: true
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: yinzhengjie-mongodb-replicaset
[root@node-exporter41 ~]#
2.将配置文件同步到集群其他节点
[root@node-exporter41 ~]# scp /yinzhengjie/softwares/mongodb/conf/mongo.conf 10.0.0.42:/yinzhengjie/softwares/mongodb/conf/
[root@node-exporter41 ~]# scp /yinzhengjie/softwares/mongodb/conf/mongo.conf 10.0.0.43:/yinzhengjie/softwares/mongodb/conf/
3.重启MongoDB服务
[root@node-exporter41 ~]# systemctl restart mongod.service
[root@node-exporter42 ~]# systemctl restart mongod.service
[root@node-exporter43 ~]# systemctl restart mongod.service
3.任意配置复制集1主2从
[root@node-exporter41 ~]# mongosh
Current Mongosh Log ID: 67e555e5e32a8bef1201337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
test> config={_id:"yinzhengjie-mongodb-replicaset",members:[{_id:0,host: '10.0.0.41:27017'},{_id:1,host: '10.0.0.42:27017'},{_id:2,host: '10.0.0.43:27017'}]}
{
_id: 'yinzhengjie-mongodb-replicaset',
members: [
{ _id: 0, host: '10.0.0.41:27017' },
{ _id: 1, host: '10.0.0.42:27017' },
{ _id: 2, host: '10.0.0.43:27017' }
]
}
test> printjson(config)
{
_id: 'yinzhengjie-mongodb-replicaset',
members: [
{
_id: 0,
host: '10.0.0.41:27017'
},
{
_id: 1,
host: '10.0.0.42:27017'
},
{
_id: 2,
host: '10.0.0.43:27017'
}
]
}
test>
核心代码:
config={_id:"yinzhengjie-mongodb-replicaset",members:[{_id:0,host: '10.0.0.41:27017'},{_id:1,host: '10.0.0.42:27017'},{_id:2,host: '10.0.0.43:27017'}]}
4.任意节点初始化并启动复制集
1.任意节点(比如"node-exporter41")初始化配置,观察命令行提示符
[root@node-exporter41 ~]# mongosh
Current Mongosh Log ID: 67e555e5e32a8bef1201337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
------
test>
test> rs.initiate(config) # 启动初始化配置
{
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743083079, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743083079, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: secondary] test>
yinzhengjie-mongodb-replicaset [direct: secondary] test> rs.isMaster() # 判断谁是主节点
{
topologyVersion: {
processId: ObjectId('67e5550a9b7591f5aa99f1b9'),
counter: Long('4')
},
hosts: [ '10.0.0.41:27017', '10.0.0.42:27017', '10.0.0.43:27017' ],
setName: 'yinzhengjie-mongodb-replicaset',
setVersion: 1,
ismaster: false,
secondary: true,
primary: '10.0.0.43:27017', # 注意哈,主节点时43节点哟~
me: '10.0.0.41:27017',
lastWrite: {
opTime: { ts: Timestamp({ t: 1743083469, i: 1 }), t: Long('1') },
lastWriteDate: ISODate('2025-03-27T13:51:09.000Z'),
majorityOpTime: { ts: Timestamp({ t: 1743083469, i: 1 }), t: Long('1') },
majorityWriteDate: ISODate('2025-03-27T13:51:09.000Z')
},
maxBsonObjectSize: 16777216,
maxMessageSizeBytes: 48000000,
maxWriteBatchSize: 100000,
localTime: ISODate('2025-03-27T13:51:13.152Z'),
logicalSessionTimeoutMinutes: 30,
connectionId: 2,
minWireVersion: 0,
maxWireVersion: 25,
readOnly: false,
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743083469, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743083469, i: 1 }),
isWritablePrimary: false
}
yinzhengjie-mongodb-replicaset [direct: secondary] test>
2.观察"node-exporter42"节点命令行提示符
[root@node-exporter42 ~]# mongosh
Current Mongosh Log ID: 67e5566798e5d8e08501337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
------
yinzhengjie-mongodb-replicaset [direct: secondary] test>
2.观察"node-exporter43"节点命令行提示符
[root@node-exporter43 ~]# mongosh
Current Mongosh Log ID: 67e5571dbb93cf26c601337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
------
yinzhengjie-mongodb-replicaset [direct: primary] test>
5.添加测试数据验证配置高可用
1.主库写入测试数据
yinzhengjie-mongodb-replicaset [direct: primary] test> for(i=0;i<10000;i++){db.teacher.insertOne({tid: i, name: "杰哥讲运维"+i,age: 18,date: new Date()})}
{
acknowledged: true,
insertedId: ObjectId('67e5594cbb93cf26c6015a8a')
}
yinzhengjie-mongodb-replicaset [direct: primary] test> db.teacher.countDocuments()
10000
yinzhengjie-mongodb-replicaset [direct: primary] test>
2.从库查看数据
yinzhengjie-mongodb-replicaset [direct: secondary] test> db
test
yinzhengjie-mongodb-replicaset [direct: secondary] test> db.teacher.countDocuments()
10000
yinzhengjie-mongodb-replicaset [direct: secondary] test>
6.验证MongoDB一主两从架构高可用性
1.停止Primary节点的MongoDB服务
[root@node-exporter43 ~]# systemctl disable --now mongod.service
Removed /etc/systemd/system/multi-user.target.wants/mongod.service.
[root@node-exporter43 ~]#
2.观察MongoDB的变化
如上图所示,自动会选举出新的Primary节点哟。
3.查看集群状态
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.status()
{
set: 'yinzhengjie-mongodb-replicaset',
...,
members: [
{
_id: 0,
name: '10.0.0.41:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
...
},
{
_id: 1,
name: '10.0.0.42:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
},
{
_id: 2,
name: '10.0.0.43:27017',
health: 0,
state: 8,
stateStr: '(not reachable/healthy)', # 注意哈,我们停止服务的节点会被标记为不可达哟~记得要启动后观察这个状态变化!
...
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743084928, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743084928, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
三.MongoDB集群扩容实战
1.准备测试节点
1.卸载掉之前MongoDB旧的环境
[root@prometheus-server31 ~]# ./install-mongodb.sh r
Removed /etc/systemd/system/multi-user.target.wants/mongod.service.
(Reading database ... 155824 files and directories currently installed.)
Removing mongodb-mongosh-shared-openssl3 (2.4.2) ...
Processing triggers for man-db (2.10.2-1) ...
卸载成功,欢迎再次使用尹正杰二进制mongoDB安装脚本哟~
[root@prometheus-server31 ~]#
2.安装MongoDB基础环境
[root@prometheus-server31 ~]# ./install-mongodb.sh i
Selecting previously unselected package mongodb-mongosh-shared-openssl3.
(Reading database ... 155814 files and directories currently installed.)
Preparing to unpack mongodb-mongosh-shared-openssl3_2.4.2_amd64.deb ...
Unpacking mongodb-mongosh-shared-openssl3 (2.4.2) ...
Setting up mongodb-mongosh-shared-openssl3 (2.4.2) ...
Processing triggers for man-db (2.10.2-1) ...
YinZhengjie's MongoDB 安装完成! [ OK ]
LISTEN 0 4096 0.0.0.0:27017 0.0.0.0:*
安装成功,欢迎使用尹正杰二进制mongoDB安装脚本,欢迎下次使用!
请运行'mongosh'命令测试能否链接MongoDB服务。
[root@prometheus-server31 ~]#
2.修改新节点的配置文件
1.将集群的配置文件同步到新节点
[root@prometheus-server31 ~]# scp 10.0.0.41:/yinzhengjie/softwares/mongodb/conf/mongo.conf /yinzhengjie/softwares/mongodb/conf/
2.重启服务使得配置生效
[root@prometheus-server31 ~]# systemctl restart mongod.service
[root@prometheus-server31 ~]#
3.添加节点
1.添加节点
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.add("10.0.0.31:27017")
{
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743085151, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743085151, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
2.查看集群节点状态
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.status()
{
set: 'yinzhengjie-mongodb-replicaset',
...
members: [
{
_id: 0,
name: '10.0.0.41:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
...
},
{
_id: 1,
name: '10.0.0.42:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
},
{
_id: 2,
name: '10.0.0.43:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
},
{
_id: 3,
name: '10.0.0.31:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743085178, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743085178, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
4.移除节点
1.移除节点
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.remove("10.0.0.31:27017")
{
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743085300, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743085300, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
2.查看集群节点状态
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.status()
{
set: 'yinzhengjie-mongodb-replicaset',
...
members: [
{
_id: 0,
name: '10.0.0.41:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
...
},
{
_id: 1,
name: '10.0.0.42:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
},
{
_id: 2,
name: '10.0.0.43:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
...
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743085408, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743085408, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
5.查看集群配置
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.conf()
{
_id: 'yinzhengjie-mongodb-replicaset',
version: 7,
term: 2,
members: [
{
_id: 0,
host: '10.0.0.41:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
},
{
_id: 1,
host: '10.0.0.42:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
},
{
_id: 2,
host: '10.0.0.43:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
}
],
protocolVersion: Long('1'),
writeConcernMajorityJournalDefault: true,
settings: {
chainingAllowed: true,
heartbeatIntervalMillis: 2000,
heartbeatTimeoutSecs: 10,
electionTimeoutMillis: 10000,
catchUpTimeoutMillis: -1,
catchUpTakeoverDelayMillis: 30000,
getLastErrorModes: {},
getLastErrorDefaults: { w: 1, wtimeout: 0 },
replicaSetId: ObjectId('67e556479b7591f5aa99f1bf')
}
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
四.修改集群的master节点
1.查看集群master信息
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.isMaster()
{
topologyVersion: {
processId: ObjectId('67e5550a9b7591f5aa99f1b9'),
counter: Long('13')
},
hosts: [ '10.0.0.41:27017', '10.0.0.42:27017', '10.0.0.43:27017' ],
setName: 'yinzhengjie-mongodb-replicaset',
setVersion: 7,
ismaster: true,
secondary: false,
primary: '10.0.0.41:27017',
me: '10.0.0.41:27017',
electionId: ObjectId('7fffffff0000000000000002'),
lastWrite: {
opTime: { ts: Timestamp({ t: 1743086848, i: 1 }), t: Long('2') },
lastWriteDate: ISODate('2025-03-27T14:47:28.000Z'),
majorityOpTime: { ts: Timestamp({ t: 1743086848, i: 1 }), t: Long('2') },
majorityWriteDate: ISODate('2025-03-27T14:47:28.000Z')
},
maxBsonObjectSize: 16777216,
maxMessageSizeBytes: 48000000,
maxWriteBatchSize: 100000,
localTime: ISODate('2025-03-27T14:47:29.217Z'),
logicalSessionTimeoutMinutes: 30,
connectionId: 2,
minWireVersion: 0,
maxWireVersion: 25,
readOnly: false,
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743086848, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743086848, i: 1 }),
isWritablePrimary: true
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
2.修改节点的优先级以改变primary角色
1.定义config变量
yinzhengjie-mongodb-replicaset [direct: primary] test> config=rs.conf()
2.将43节点的优先级调高
yinzhengjie-mongodb-replicaset [direct: primary] test> config.members[2].priority=2
2
yinzhengjie-mongodb-replicaset [direct: primary] test>
3.重新应用配置
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.reconfig(config)
{
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743087276, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743087276, i: 1 })
}
yinzhengjie-mongodb-replicaset [direct: primary] test>
4.再次查看集群配置
yinzhengjie-mongodb-replicaset [direct: primary] test> rs.conf()
{
_id: 'yinzhengjie-mongodb-replicaset',
version: 8,
term: 3,
members: [
{
_id: 0,
host: '10.0.0.41:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
},
{
_id: 1,
host: '10.0.0.42:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
},
{
_id: 2,
host: '10.0.0.43:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 2, # 注意观察优先级
tags: {},
secondaryDelaySecs: Long('0'),
votes: 1
}
],
protocolVersion: Long('1'),
writeConcernMajorityJournalDefault: true,
settings: {
chainingAllowed: true,
heartbeatIntervalMillis: 2000,
heartbeatTimeoutSecs: 10,
electionTimeoutMillis: 10000,
catchUpTimeoutMillis: -1,
catchUpTakeoverDelayMillis: 30000,
getLastErrorModes: {},
getLastErrorDefaults: { w: 1, wtimeout: 0 },
replicaSetId: ObjectId('67e556479b7591f5aa99f1bf')
}
}
yinzhengjie-mongodb-replicaset [direct: secondary] test>
yinzhengjie-mongodb-replicaset [direct: secondary] test> config.members[1].priority=5
5
yinzhengjie-mongodb-replicaset [direct: secondary] test> config.members[2].priority=3
3
yinzhengjie-mongodb-replicaset [direct: secondary] test> rs.reconfig(config) # 在想修改就报错啦~说明当前节点已经不是Primary,说明我们的配置生效啦~
MongoServerError[NotWritablePrimary]: New config is rejected :: caused by :: replSetReconfig should only be run on a writable PRIMARY. Current state SECONDARY;
yinzhengjie-mongodb-replicaset [direct: secondary] test>
yinzhengjie-mongodb-replicaset [direct: secondary] test>
3.再次查看集群master信息
yinzhengjie-mongodb-replicaset [direct: secondary] test> rs.isMaster()
{
topologyVersion: {
processId: ObjectId('67e5550a9b7591f5aa99f1b9'),
counter: Long('17')
},
hosts: [ '10.0.0.41:27017', '10.0.0.42:27017', '10.0.0.43:27017' ],
setName: 'yinzhengjie-mongodb-replicaset',
setVersion: 8,
ismaster: false,
secondary: true,
primary: '10.0.0.43:27017',
me: '10.0.0.41:27017',
lastWrite: {
opTime: { ts: Timestamp({ t: 1743087626, i: 1 }), t: Long('3') },
lastWriteDate: ISODate('2025-03-27T15:00:26.000Z'),
majorityOpTime: { ts: Timestamp({ t: 1743087626, i: 1 }), t: Long('3') },
majorityWriteDate: ISODate('2025-03-27T15:00:26.000Z')
},
maxBsonObjectSize: 16777216,
maxMessageSizeBytes: 48000000,
maxWriteBatchSize: 100000,
localTime: ISODate('2025-03-27T15:00:33.043Z'),
logicalSessionTimeoutMinutes: 30,
connectionId: 2,
minWireVersion: 0,
maxWireVersion: 25,
readOnly: false,
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743087626, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743087626, i: 1 }),
isWritablePrimary: false
}
yinzhengjie-mongodb-replicaset [direct: secondary] test>
五.配置仲裁节点实战
1.快速初始化MongoDB环境
1.卸载旧的MongoDB环境
[root@node-exporter41 ~]# ./install-mongodb.sh r
[root@node-exporter42 ~]# ./install-mongodb.sh r
[root@node-exporter43 ~]# ./install-mongodb.sh r
2.重新安装MongoDB环境
[root@node-exporter41 ~]# ./install-mongodb.sh i
[root@node-exporter42 ~]# ./install-mongodb.sh i
[root@node-exporter43 ~]# ./install-mongodb.sh i
2.准备集群的配置文件
1.编写配置文件
[root@node-exporter41 ~]# cat /yinzhengjie/softwares/mongodb/conf/mongo.conf
systemLog:
destination: file
path: "/yinzhengjie/softwares/mongodb/log/mongodb.log"
logAppend: true
storage:
dbPath: "/yinzhengjie/softwares/mongodb/data/"
journal:
commitIntervalMs: 100
processManagement:
fork: true
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: yinzhengjie-mongodb-replicaset-arbiter
[root@node-exporter41 ~]#
2.同步配置文件到其他节点
[root@node-exporter41 ~]# scp /yinzhengjie/softwares/mongodb/conf/mongo.conf 10.0.0.42:/yinzhengjie/softwares/mongodb/conf/
[root@node-exporter41 ~]# scp /yinzhengjie/softwares/mongodb/conf/mongo.conf 10.0.0.43:/yinzhengjie/softwares/mongodb/conf/
3.重启服务使得配置生效
[root@node-exporter41 ~]# systemctl restart mongod.service
[root@node-exporter42 ~]# systemctl restart mongod.service
[root@node-exporter43 ~]# systemctl restart mongod.service
3.验证primary,arbiter,secondary权限
1.主库可以写入数据
[root@node-exporter41 ~]# mongosh
Current Mongosh Log ID: 67e555e5e32a8bef1201337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
test> config={_id:"yinzhengjie-mongodb-replicaset-arbiter",members:[{_id:0,host: '10.0.0.41:27017'},{_id:1,host: '10.0.0.42:27017','arbiterOnly': true},{_id:2,host: '10.0.0.43:27017'}]}
{
_id: 'yinzhengjie-mongodb-replicaset-arbiter',
members: [
{ _id: 0, host: '10.0.0.41:27017' },
{ _id: 1, host: '10.0.0.42:27017', arbiterOnly: true },
{ _id: 2, host: '10.0.0.43:27017' }
]
}
test> printjson(config)
{
_id: 'yinzhengjie-mongodb-replicaset-arbiter',
members: [
{
_id: 0,
host: '10.0.0.41:27017'
},
{
_id: 1,
host: '10.0.0.42:27017',
arbiterOnly: true
},
{
_id: 2,
host: '10.0.0.43:27017'
}
]
}
test> rs.initiate(config)
{
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1743088546, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1743088546, i: 1 })
}
yinzhengjie-mongodb-replicaset-arbiter [direct: primary] test>
yinzhengjie-mongodb-replicaset-arbiter [direct: primary] test> use xixi
switched to db xixi
yinzhengjie-mongodb-replicaset-arbiter [direct: primary] xixi> db.t1.insertOne({name: "哈哈"});
{
acknowledged: true,
insertedId: ObjectId('67e56c7203f352f28601337b')
}
yinzhengjie-mongodb-replicaset-arbiter [direct: primary] xixi>
2.arbiter角色节点无法查询数据
[root@node-exporter42 ~]# mongosh
Current Mongosh Log ID: 67e56bcf92f0c190c801337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
The server generated these startup warnings when booting
2025-03-27T23:15:05.681+08:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2025-03-27T23:15:07.258+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2025-03-27T23:15:07.258+08:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
2025-03-27T23:15:07.258+08:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
2025-03-27T23:15:07.258+08:00: We suggest setting the contents of sysfsFile to 0.
2025-03-27T23:15:07.258+08:00: Your system has glibc support for rseq built in, which is not yet supported by tcmalloc-google and has critical performance implications. Please set the environment variable GLIBC_TUNABLES=glibc.pthread.rseq=0
2025-03-27T23:15:07.258+08:00: vm.max_map_count is too low
2025-03-27T23:15:07.258+08:00: We suggest setting swappiness to 0 or 1, as swapping can cause performance problems.
2025-03-27T23:15:46.722+08:00: ** WARNING: Arbiters are not supported in quarterly binary versions
------
yinzhengjie-mongodb-replicaset-arbiter [direct: arbiter] test> show dbs
MongoServerError[NotPrimaryOrSecondary]: node is not in primary or recovering state
yinzhengjie-mongodb-replicaset-arbiter [direct: arbiter] test>
3.secondary角色可以查询数据,但无法写入数据
[root@node-exporter43 ~]# mongosh
Current Mongosh Log ID: 67e56c0c46164aa50601337a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB: 8.0.5
Using Mongosh: 2.4.2
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
...
------
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] test> show dbs
admin 80.00 KiB
config 128.00 KiB
local 420.00 KiB
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] test>
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] xixi> db.t1.insertOne({name: "嘻嘻"});
MongoServerError[NotWritablePrimary]: not primary
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] xixi>
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] xixi> show tables
t1
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] xixi> db.t1.find()
[ { _id: ObjectId('67e56c7203f352f28601337b'), name: '哈哈' } ]
yinzhengjie-mongodb-replicaset-arbiter [direct: secondary] xixi>
核心代码:
config={_id:"yinzhengjie-mongodb-replicaset-arbiter",members:[{_id:0,host: '10.0.0.41:27017'},{_id:1,host: '10.0.0.42:27017','arbiterOnly': true},{_id:2,host: '10.0.0.43:27017'}]}
本文来自博客园,作者:尹正杰,转载请注明原文链接:https://www.cnblogs.com/yinzhengjie/p/18792668,个人微信: "JasonYin2020"(添加时请备注来源及意图备注,有偿付费)
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。