点击上方蓝字关注我
MongoDB的副本集(Replica Set)是一个高可用性、可扩展性和冗余性的数据库解决方案。它能够确保数据库的高可用性,同时保障了数据的安全性。在本文中,我们将探讨如何在一个已经包含三个数据节点的副本集集群中,添加一个仲裁节点,并同时删除原先的一个数据节点。
1. 副本集的基本概念
MongoDB副本集由多个数据节点+若干个仲裁节点(可以没有)组成,其中一个数据节点被选举为主节点(Primary),其余节点为次要节点(Secondary)。在故障时,副本集会自动进行主节点的切换,确保服务的高可用性。副本集中的仲裁节点(Arbiter)不存储数据,仅用于选举过程,帮助副本集进行决策。
例如,当前配置一个3节点的数据节点集群,组件集群命令如下:
- > use admin
- > rs.initiate( {_id: "test1",members: [{ _id: 0, host: "192.168.122.36:27017" },{ _id: 1, host: "192.168.122.36:27018" },{ _id: 2, host: "192.168.122.36:27019" } ] })
查看状态:
- test1:PRIMARY> use admin
- switched to db admin
- test1:PRIMARY> rs.status()
- {
- "set" : "test1",
- "date" : ISODate("2023-10-23T02:31:02.345Z"),
- "myState" : 1,
- "term" : NumberLong(1),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "heartbeatIntervalMillis" : NumberLong(2000),
- "majorityVoteCount" : 2,
- "writeMajorityCount" : 2,
- "optimes" : {
- "lastCommittedOpTime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "lastCommittedWallTime" : ISODate("2023-10-23T02:30:54.919Z"),
- "readConcernMajorityOpTime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "readConcernMajorityWallTime" : ISODate("2023-10-23T02:30:54.919Z"),
- "appliedOpTime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "durableOpTime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "lastAppliedWallTime" : ISODate("2023-10-23T02:30:54.919Z"),
- "lastDurableWallTime" : ISODate("2023-10-23T02:30:54.919Z")
- },
- "lastStableRecoveryTimestamp" : Timestamp(1698028224, 3),
- "lastStableCheckpointTimestamp" : Timestamp(1698028224, 3),
- "electionCandidateMetrics" : {
- "lastElectionReason" : "electionTimeout",
- "lastElectionDate" : ISODate("2023-10-23T02:30:24.838Z"),
- "electionTerm" : NumberLong(1),
- "lastCommittedOpTimeAtElection" : {
- "ts" : Timestamp(0, 0),
- "t" : NumberLong(-1)
- },
- "lastSeenOpTimeAtElection" : {
- "ts" : Timestamp(1698028214, 1),
- "t" : NumberLong(-1)
- },
- "numVotesNeeded" : 2,
- "priorityAtElection" : 1,
- "electionTimeoutMillis" : NumberLong(10000),
- "numCatchUpOps" : NumberLong(0),
- "newTermStartDate" : ISODate("2023-10-23T02:30:24.912Z"),
- "wMajorityWriteAvailabilityDate" : ISODate("2023-10-23T02:30:25.497Z")
- },
- "members" : [
- {
- "_id" : 0,
- "name" : "192.168.122.36:27017",
- "health" : 1,
- "state" : 1,
- "stateStr" : "PRIMARY",
- "uptime" : 183,
- "optime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T02:30:54Z"),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "could not find member to sync from",
- "electionTime" : Timestamp(1698028224, 1),
- "electionDate" : ISODate("2023-10-23T02:30:24Z"),
- "configVersion" : 1,
- "self" : true,
- "lastHeartbeatMessage" : ""
- },
- {
- "_id" : 1,
- "name" : "192.168.122.36:27018",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 47,
- "optime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T02:30:54Z"),
- "optimeDurableDate" : ISODate("2023-10-23T02:30:54Z"),
- "lastHeartbeat" : ISODate("2023-10-23T02:31:00.889Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T02:31:01.443Z"),
- "pingMs" : NumberLong(0),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "192.168.122.36:27017",
- "syncSourceHost" : "192.168.122.36:27017",
- "syncSourceId" : 0,
- "infoMessage" : "",
- "configVersion" : 1
- },
- {
- "_id" : 2,
- "name" : "192.168.122.36:27019",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 47,
- "optime" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1698028254, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T02:30:54Z"),
- "optimeDurableDate" : ISODate("2023-10-23T02:30:54Z"),
- "lastHeartbeat" : ISODate("2023-10-23T02:31:00.890Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T02:31:01.446Z"),
- "pingMs" : NumberLong(0),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "192.168.122.36:27017",
- "syncSourceHost" : "192.168.122.36:27017",
- "syncSourceId" : 0,
- "infoMessage" : "",
- "configVersion" : 1
- }
- ],
- "ok" : 1,
- "$clusterTime" : {
- "clusterTime" : Timestamp(1698028254, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- },
- "operationTime" : Timestamp(1698028254, 1)
- }
此时可以用一个程序验证集群的可用情况:
- from pymongo import MongoClient
- from pymongo.errors import ConnectionFailure
-
-
- # MongoDB副本集的连接信息
- replica_set = "test1"
- mongo_host = ["192.168.122.36:27017", "192.168.122.36:27018", "192.168.122.36:27019"] # 主机和端口号列表
-
-
- # 尝试连接MongoDB副本集
- try:
- client = MongoClient(mongo_host, replicaSet=replica_set, serverSelectionTimeoutMS=5000)
- db = client["testdb"]
- print("Successfully connected to MongoDB replica set.")
- collection = db['test1']
- data = {"b":2}
- result = collection.insert_one(data)
-
-
-
-
- except ConnectionFailure:
- print("Failed to connect to MongoDB replica set. Please check your connection settings.")
运行结果如下:
查看数据库中运行结果:
2. 添加节点
要添加一个仲裁节点,我们需要在现有副本集中的任一节点上执行如下操作:
rs.add( { host: "IP:PORT", arbiterOnly:true } )
执行这个命令后,MongoDB将会在副本集中添加一个仲裁节点,增加了选主的稳定性,同时不会增加数据存储的压力。具体实际案例如下
- test1:PRIMARY> use admin
- switched to db admin
- test1:PRIMARY> rs.add( { host: "192.168.122.36:27020", arbiterOnly:true } )
- {
- "ok" : 1,
- "$clusterTime" : {
- "clusterTime" : Timestamp(1698030806, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- },
- "operationTime" : Timestamp(1698030806, 1)
- }
- test1:PRIMARY> rs.status();
- {
- "set" : "test1",
- "date" : ISODate("2023-10-23T03:13:32.511Z"),
- "myState" : 1,
- "term" : NumberLong(1),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "heartbeatIntervalMillis" : NumberLong(2000),
- "majorityVoteCount" : 3,
- "writeMajorityCount" : 3,
- "optimes" : {
- "lastCommittedOpTime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "lastCommittedWallTime" : ISODate("2023-10-23T03:13:26.379Z"),
- "readConcernMajorityOpTime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "readConcernMajorityWallTime" : ISODate("2023-10-23T03:13:26.379Z"),
- "appliedOpTime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "durableOpTime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "lastAppliedWallTime" : ISODate("2023-10-23T03:13:26.379Z"),
- "lastDurableWallTime" : ISODate("2023-10-23T03:13:26.379Z")
- },
- "lastStableRecoveryTimestamp" : Timestamp(1698030805, 1),
- "lastStableCheckpointTimestamp" : Timestamp(1698030805, 1),
- "electionCandidateMetrics" : {
- "lastElectionReason" : "electionTimeout",
- "lastElectionDate" : ISODate("2023-10-23T02:30:24.838Z"),
- "electionTerm" : NumberLong(1),
- "lastCommittedOpTimeAtElection" : {
- "ts" : Timestamp(0, 0),
- "t" : NumberLong(-1)
- },
- "lastSeenOpTimeAtElection" : {
- "ts" : Timestamp(1698028214, 1),
- "t" : NumberLong(-1)
- },
- "numVotesNeeded" : 2,
- "priorityAtElection" : 1,
- "electionTimeoutMillis" : NumberLong(10000),
- "numCatchUpOps" : NumberLong(0),
- "newTermStartDate" : ISODate("2023-10-23T02:30:24.912Z"),
- "wMajorityWriteAvailabilityDate" : ISODate("2023-10-23T02:30:25.497Z")
- },
- "members" : [
- {
- "_id" : 0,
- "name" : "192.168.122.36:27017",
- "health" : 1,
- "state" : 1,
- "stateStr" : "PRIMARY",
- "uptime" : 2733,
- "optime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T03:13:26Z"),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "electionTime" : Timestamp(1698028224, 1),
- "electionDate" : ISODate("2023-10-23T02:30:24Z"),
- "configVersion" : 2,
- "self" : true,
- "lastHeartbeatMessage" : ""
- },
- {
- "_id" : 1,
- "name" : "192.168.122.36:27018",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 2597,
- "optime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T03:13:26Z"),
- "optimeDurableDate" : ISODate("2023-10-23T03:13:26Z"),
- "lastHeartbeat" : ISODate("2023-10-23T03:13:32.393Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T03:13:32.420Z"),
- "pingMs" : NumberLong(1),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "configVersion" : 2
- },
- {
- "_id" : 2,
- "name" : "192.168.122.36:27019",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 2597,
- "optime" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1698030806, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T03:13:26Z"),
- "optimeDurableDate" : ISODate("2023-10-23T03:13:26Z"),
- "lastHeartbeat" : ISODate("2023-10-23T03:13:32.393Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T03:13:32.445Z"),
- "pingMs" : NumberLong(1),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "configVersion" : 2
- },
- {
- "_id" : 3,
- "name" : "192.168.122.36:27020",
- "health" : 1,
- "state" : 7,
- "stateStr" : "ARBITER",
- "uptime" : 6,
- "lastHeartbeat" : ISODate("2023-10-23T03:13:32.405Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T03:13:32.455Z"),
- "pingMs" : NumberLong(4),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "configVersion" : 2
- }
- ],
- "ok" : 1,
- "$clusterTime" : {
- "clusterTime" : Timestamp(1698030806, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- },
- "operationTime" : Timestamp(1698030806, 1)
- }
此时修改python中程序(插入的数据),运行结果如下:
3. 删除数据节点
如果你需要删除一个数据节点,首先,你要确保副本集的健康状态,然后执行如下操作来删除一个Secondary节点。
rs.remove("IP:PORT");
执行这个命令后,MongoDB将从副本集中移除该数据节点,副本集会重新进行选举,确保副本集的高可用性。
- test1:PRIMARY> rs.remove("192.168.122.36:27019")
- {
- "ok" : 1,
- "$clusterTime" : {
- "clusterTime" : Timestamp(1698038888, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- },
- "operationTime" : Timestamp(1698038888, 1)
- }
- test1:PRIMARY> rs.status
- function() {
- return db._adminCommand("replSetGetStatus"); # 选举中
- }
- test1:PRIMARY> rs.status()
- {
- "set" : "test1",
- "date" : ISODate("2023-10-23T05:28:15.398Z"),
- "myState" : 1,
- "term" : NumberLong(1),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "heartbeatIntervalMillis" : NumberLong(2000),
- "majorityVoteCount" : 2,
- "writeMajorityCount" : 2,
- "optimes" : {
- "lastCommittedOpTime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "lastCommittedWallTime" : ISODate("2023-10-23T05:28:08.335Z"),
- "readConcernMajorityOpTime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "readConcernMajorityWallTime" : ISODate("2023-10-23T05:28:08.335Z"),
- "appliedOpTime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "durableOpTime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "lastAppliedWallTime" : ISODate("2023-10-23T05:28:08.335Z"),
- "lastDurableWallTime" : ISODate("2023-10-23T05:28:08.335Z")
- },
- "lastStableRecoveryTimestamp" : Timestamp(1698038845, 1),
- "lastStableCheckpointTimestamp" : Timestamp(1698038845, 1),
- "electionCandidateMetrics" : {
- "lastElectionReason" : "electionTimeout",
- "lastElectionDate" : ISODate("2023-10-23T02:30:24.838Z"),
- "electionTerm" : NumberLong(1),
- "lastCommittedOpTimeAtElection" : {
- "ts" : Timestamp(0, 0),
- "t" : NumberLong(-1)
- },
- "lastSeenOpTimeAtElection" : {
- "ts" : Timestamp(1698028214, 1),
- "t" : NumberLong(-1)
- },
- "numVotesNeeded" : 2,
- "priorityAtElection" : 1,
- "electionTimeoutMillis" : NumberLong(10000),
- "numCatchUpOps" : NumberLong(0),
- "newTermStartDate" : ISODate("2023-10-23T02:30:24.912Z"),
- "wMajorityWriteAvailabilityDate" : ISODate("2023-10-23T02:30:25.497Z")
- },
- "members" : [
- {
- "_id" : 0,
- "name" : "192.168.122.36:27017",
- "health" : 1,
- "state" : 1,
- "stateStr" : "PRIMARY",
- "uptime" : 10816,
- "optime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T05:28:08Z"),
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "electionTime" : Timestamp(1698028224, 1),
- "electionDate" : ISODate("2023-10-23T02:30:24Z"),
- "configVersion" : 3,
- "self" : true,
- "lastHeartbeatMessage" : ""
- },
- {
- "_id" : 1,
- "name" : "192.168.122.36:27018",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 10680,
- "optime" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1698038888, 1),
- "t" : NumberLong(1)
- },
- "optimeDate" : ISODate("2023-10-23T05:28:08Z"),
- "optimeDurableDate" : ISODate("2023-10-23T05:28:08Z"),
- "lastHeartbeat" : ISODate("2023-10-23T05:28:14.347Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T05:28:15.388Z"),
- "pingMs" : NumberLong(1),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "configVersion" : 3
- },
- {
- "_id" : 3,
- "name" : "192.168.122.36:27020",
- "health" : 1,
- "state" : 7,
- "stateStr" : "ARBITER",
- "uptime" : 8088,
- "lastHeartbeat" : ISODate("2023-10-23T05:28:14.342Z"),
- "lastHeartbeatRecv" : ISODate("2023-10-23T05:28:14.369Z"),
- "pingMs" : NumberLong(0),
- "lastHeartbeatMessage" : "",
- "syncingTo" : "",
- "syncSourceHost" : "",
- "syncSourceId" : -1,
- "infoMessage" : "",
- "configVersion" : 3
- }
- ],
- "ok" : 1,
- "$clusterTime" : {
- "clusterTime" : Timestamp(1698038888, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- },
- "operationTime" : Timestamp(1698038888, 1)
- }
注意:复制集将会短暂的关闭连接并进入选举,选举出一个新的主节点。接口将会自动重连。接口可能将会报错 DBClientCursor::init call() failed 。
往期精彩回顾
4. 监控利器出鞘:Prometheus+Grafana监控MySQL、Redis数据库
5. PostgreSQL主从复制--物理复制
6. MySQL传统点位复制在线转为GTID模式复制
扫码关注