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'}]}
posted @ 2025-03-26 01:21  尹正杰  阅读(292)  评论(0)    收藏  举报