代码改变世界

【MongoDB】复制集转换成单机模式

2023-02-27 20:50  abce  阅读(510)  评论(0编辑  收藏  举报

提醒:
1.不建议生产环境使用单机模式
2.切换需要停机时间(需要移除复制参数)
3.切换前建议关闭应用,避免有写操作生产环境是一个三节点的复制集

[
  {
    "_id" : 0,
    "name" : "node01:27017",
    "stateStr" : "PRIMARY"
  },
  {
    "_id" : 1,
    "name" : "node02:27017",
    "stateStr" : "SECONDARY",
  },
  {
    "_id" : 2,
    "name" : "node03:27017",
    "stateStr" : "SECONDARY",
]

这里将primary节点切换成单节点后的使用环境。

1.移除复制节点
移除第二节点:

rs0:PRIMARY> rs.remove("node02:27017")
{
  "ok" : 1,
  "$clusterTime" : {
    "clusterTime" : Timestamp(1640109346, 1),
    "signature" : {
      "hash" : BinData(0,"663Y5u3GkZkQ0Ci7EU8IYUldVIM="),
      "keyId" : NumberLong("7044208418021703684")
    }
  },
  "operationTime" : Timestamp(1640109346, 1)
}

移除第三节点:

rs0:PRIMARY> rs.remove("node03:27017")
{
  "ok" : 1,
  "$clusterTime" : {
    "clusterTime" : Timestamp(1640109380, 1),
    "signature" : {
      "hash" : BinData(0,"RReAzLZmHWfzVcdnLoGJ/uz04Vo="),
      "keyId" : NumberLong("7044208418021703684")
    }
  },
  "operationTime" : Timestamp(1640109380, 1)
}

移除后查看状态:

rs0:PRIMARY> rs.status().members
[
  {
    "_id" : 0,
    "name" : "node01:27017",
    "health" : 1,
    "state" : 1,
    "stateStr" : "PRIMARY",
    "uptime" : 1988,
    "optime" : {
      "ts" : Timestamp(1640109560, 1),
      "t" : NumberLong(1)
    },
    "optimeDate" : ISODate("2021-12-21T17:59:20Z"),
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "infoMessage" : "",
    "electionTime" : Timestamp(1640107580, 2),
    "electionDate" : ISODate("2021-12-21T17:26:20Z"),
    "configVersion" : 5,
    "configTerm" : 1,
    "self" : true,
    "lastHeartbeatMessage" : ""
  }
]

2.修改配置尽管节点1和节点2不再是复制集的成员,但是还是建议关闭这两个节点的mongodb实例。保持他们数据的安全,也许在有些恢复场景下用的上。

node02> systemctl stop mongod
node03> systemctl stop mongod

移除复制集相关的参数:

#replication:
#  replSetName: "rs0"

重启mongodb实例:

node01> systemctl restart mongod

3.移除复制对象
这个时候连接到单节点的mongodb,日志会给出警告信息:

2021-12-21T18:23:52.056+00:00: Document(s) exist in 'system.replset', but started without --replSet. Database contents may appear inconsistent with the writes that were visible when this node0 was running as part of a replica set. Restart with --replSet unless you are doing maintenance and no other clients are connected. The TTL collection monitor will not start because of this. For more info see http://dochub.mongodb.org/core/ttlcollections

这是因为老的复制集结构的数据仍然存在的。

mongo> use local
switched to db local
​
mongo> show collections
oplog.rs
replset.election
replset.initialSyncId
replset.minvalid
replset.oplogTruncateAfterPoint
startup_log
system.replset
system.rollback.id
system.tenantMigration.oplogView
system.views

要想去掉日志中的警告信息,需要移除这些复制集的对象local.system.replset。
不过local.system.replset是系统对象,没有任何内嵌的角色可以被用来移除该对象。除非你创建了一个角色,授予在anyResource上有anyAction权限;或者你给用户授予了内部角色__system。
这里,我们可以临时创建一个对象,授予__system特权,后面可以删掉该用户:

mongo> db.getSiblingDB("admin").createUser({user: "dba_system", "pwd": "pwd123","roles" : [{ "db" : "admin", "role" : "__system" }]});
Successfully added user:{
   "user":"dba_system",
   "roles":[
      {
         "db":"admin",
         "role":"__system"
      }
   ]
}

创建临时用户后,删除对象:

mongo> use local;
mongo> db.system.replset.remove({})
WriteResult({ "nRemoved" : 1 })

删除临时用户

mongo> db.dropUser("dba_system")

重启mongodb实例

shell> systemctl restart mongod

另一个更简单的选择是删除额外的成员,并将其保留为单成员复制集-乍一看可能很愚蠢,但它提供了一些灵活性!