MongoDB 副本集搭建 【docker compose + 本机部署】【建议收藏起来】

news2024/10/2 3:38:17

什么是副本集

MongoDB副本集(Replica Set)是一种数据冗余和故障恢复机制,它允许你维护相同数据的一个或多个副本,并提供自动故障转移和数据恢复能力。副本集是一个包含多个MongoDB实例(通常称为成员)的集合,其中一个成员被选举为主节点(Primary),其他成员作为从节点(Secondary)或仲裁节点(Arbiter)。

副本集的角色:

  • 主节点(Primary):负责处理客户端的读写请求,并将数据更改写入其本地数据文件中。同时,主节点还会将这些更改记录在一个名为oplog(操作日志)的特殊日志文件中,并异步地复制给从节点。
  • 从节点(Secondary):从主节点复制数据,并在本地存储一份副本。默认情况下,从节点默认不处理客户端的读请求,但你可以将其配置为可以读取,从而分散读请求并提高性能。在发生故障时,一个从节点可以被选举为主节点。
  • 仲裁节点(Arbiter):只参与故障转移投票,不存储数据。它通常用于确保副本集具有奇数个成员(以实现多数投票),同时减少存储成本。

副本集的工作机制:

  • 数据复制:主节点将oplog中的更改异步复制到从节点。
  • 故障转移:如果主节点不可用,副本集中的其他成员将尝试选举一个新的主节点。这个过程基于心跳检测和投票机制。
  • 读请求路由:客户端可以将读请求发送到主节点或从节点(如果配置为可读)。

副本集至少需要3个成员,可以配置为一主两从
在这里插入图片描述
如果主节点挂掉,两个从节点会重新选举,找到一个从节点,将其提升为主
在这里插入图片描述
在某些情况下(例如存在一个主节点和一个从节点,但由于成本有限无法再添加另一个从节点),您可以选择将一个实例配置为仲裁节点添加到副本集中。仲裁节点参与选举,但不持有数据(即不提供数据冗余):
在这里插入图片描述
在选举时,主节点可能降为从节点,从节点也可能提升为主节点,但仲裁节点永远只能是仲裁节点。

数据同步原理

Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。如果某个操作失败,则secondary节点停止从当前数据源复制数据。如果某个secondary节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog,由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB的oplog的操作是幂等的,也就是说将oplog的同一个操作执行多次,与执行一次的效果是一样的:

当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步:

  1. 检查自己local库的oplog.rs集合找出最近的时间戳。
  2. 检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。
  3. 将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。

secondary从primary端获取日志,然后在本地完全顺序的执行oplog所记录的各种操作(oplog不记录查询操作),这个日志就是local数据库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定: --oplogSize 1000,单位是M。

注意:在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。

部署

Docker compose 部署

创建目录

mkdir -p /mongodb/data

编写 docker-compose.yml 文件

services:
  mongo:
    image: mongo:7.0
    container_name: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
      MONGO_INITDB_REPLICA_SET_NAME: rs0
    ports:
      - 27017:27017
    volumes:
      - mongodb-data:/data/db
      - /mongodb/mongodb-keyfile:/data/mongodb-keyfile
    command:
      - /bin/sh
      - -c
      - |
        chmod 400 /mongodb/mongodb-keyfile
        chown 999:999 /mongodb/mongodb-keyfile
        mongod --replSet rs0 --keyFile /data/mongodb-keyfile --bind_ip_all
volumes:
  mongodb-data:

所有主机的 yml 文件是一致的
这个时候不要着急启动 docker
先生成一份 key

openssl rand -base64 756 > mongodb-keyfile

开始启动容器

docker compose up -d

当然这句话要在 /mongodb 文件夹下使用
查看集群状态

docker exec -it mongo mongosh -u root -p 123456 --authenticationDatabase admin

在随机一台主机上执行,或者你想让哪台主机成为 leader 你就在哪台主机上执行

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "192.168.142.157:27017" },
    { _id: 1, host: "192.168.142.156:27017" },
    { _id: 2, host: "192.168.142.155:27017" },
    { _id: 3, host: "192.168.142.158:27017" }
  ]
})

另外,如果 上面这个操作执行不成功的话,可以分开执行

rs.initiate()

这个地方是除了本机,都加上,效果按理来说是和上面那种方式是一样的

rs.add("192.168.142.156:27017")  // 添加第一个从节点
rs.add("192.168.142.155:27017")  // 添加第二个从节点
rs.add("192.168.142.158:27017")  // 添加第三个从节点

进入 mongodb 的 shell 平台之后再使用

rs.status()

查看集群状态

{
  set: 'rs0',
  date: ISODate('2024-10-01T12:20:28.852Z'),
  myState: 1,
  term: Long('1'),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long('2000'),
  majorityVoteCount: 1,
  writeMajorityCount: 1,
  votingMembersCount: 1,
  writableVotingMembersCount: 1,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1727785225, i: 1 }), t: Long('1') },
    lastCommittedWallTime: ISODate('2024-10-01T12:20:25.424Z'),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1727785225, i: 1 }), t: Long('1') },
    appliedOpTime: { ts: Timestamp({ t: 1727785225, i: 1 }), t: Long('1') },
    durableOpTime: { ts: Timestamp({ t: 1727785225, i: 1 }), t: Long('1') },
    lastAppliedWallTime: ISODate('2024-10-01T12:20:25.424Z'),
    lastDurableWallTime: ISODate('2024-10-01T12:20:25.424Z')
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1727785185, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate('2024-10-01T12:15:55.481Z'),
    electionTerm: Long('1'),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1727784955, i: 1 }), t: Long('-1') },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1727784955, i: 1 }), t: Long('-1') },
    numVotesNeeded: 1,
    priorityAtElection: 1,
    electionTimeoutMillis: Long('10000'),
    newTermStartDate: ISODate('2024-10-01T12:15:55.492Z'),
    wMajorityWriteAvailabilityDate: ISODate('2024-10-01T12:15:55.499Z')
  },
  members: [
    {
      _id: 0,
      name: '151fa19ef0c8:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 683,
      optime: { ts: Timestamp({ t: 1727785225, i: 1 }), t: Long('1') },
      optimeDate: ISODate('2024-10-01T12:20:25.000Z'),
      lastAppliedWallTime: ISODate('2024-10-01T12:20:25.424Z'),
      lastDurableWallTime: ISODate('2024-10-01T12:20:25.424Z'),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1727784955, i: 2 }),
      electionDate: ISODate('2024-10-01T12:15:55.000Z'),
      configVersion: 4,
      configTerm: 1,
      self: true,
      lastHeartbeatMessage: ''
    },
    {
      _id: 1,
      name: '192.168.142.156:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T12:20:27.429Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    },
    {
      _id: 2,
      name: '192.168.142.155:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T12:20:27.428Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    },
    {
      _id: 3,
      name: '192.168.142.158:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T12:20:27.429Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1727785225, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('MfUjNuJ+qWiRTAB699IlXMoOlU0=', 0),
      keyId: Long('7420779876245831686')
    }
  },
  operationTime: Timestamp({ t: 1727785225, i: 1 })
}

看 members 有几个对象,我这里有三个,说明我们的副本集终于搭建成功了

大家还要注意的一点是,rs.initiate() 只能在主节点上执行,rs.ststus() 也只有主节点上能查看副本集信息,其他的节点在没有执行 rs.initiate() 时,执行 rs.status() 还是会报错的

MongoServerError[NotYetInitialized]: no replset config has been received

虽然我对这种设计有点摸不着头脑,但是这是正常的,反正这样部署是没问题的

普通部署

首先,我们需要在每一台主机上先安装好 mongodb ,这里我直接使用脚本安装,有需要的小伙伴可以去看一下我之前的一篇 mongodb 的单机部署的博客我有分享我的脚本

链接:https://blog.csdn.net/qq_62866151/article/details/142662644?spm=1001.2014.3001.5501

先创建一个 mongo 文件夹,进入文件夹

mkdir -p /mongo/data

data目录是存放数据的,我们 cd 到它的上一级即可

cd /mongo

拿到脚本之后给脚本执行权限

chmod u+x mongo_setup.sh

运行脚本

./mongo_setup.sh

安装完毕之后依据脚本最后打印的几条命令依次执行,最终

root@master:/mongo# systemctl status mongod
● mongod.service - MongoDB Database Server
     Loaded: loaded (/lib/systemd/system/mongod.service; disabled; vendor preset: enab>
     Active: active (running) since Tue 2024-10-01 13:54:32 UTC; 4min 53s ago
       Docs: https://docs.mongodb.org/manual
   Main PID: 98050 (mongod)
     Memory: 72.9M
        CPU: 1.150s
     CGroup: /system.slice/mongod.service
             └─98050 /usr/bin/mongod --config /etc/mongod.conf

Oct 01 13:54:32 master systemd[1]: Started MongoDB Database Server.
Oct 01 13:54:32 master mongod[98050]: {"t":{"$date":"2024-10-01T13:54:32.853Z"},"s":"I>

表示 mongodb 部署成功了

接下来我们去修改一下相关的配置文件

vim /etc/mongod.conf

悠着点改

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0

#security:
security:
  authorization: enabled
  keyFile: "/mongo/mongo.key"
  clusterAuthMode: "keyFile"
#operationProfiling:

#replication:
replication:
  replSetName: "rs0"
  oplogSizeMB: 5000

改完之后不要忘记,之前 docker 部署的时候还生成过 mongodb-keyfile

 openssl rand -base64 666 > /mongo/mongo.key
chmod 400 /mongo/mongo.key

创建用户

useradd -M mongodb
passwd mongodb
<密码自定义>
chown mongodb:mongodb -R /mongo

重启

systemctl restart mongod.service

这个地方的 key 文件和上面的 docker 部署的那个 key 还是有点差别的
使用 mongosh 命令进入 mongodb 的 shell 界面
首先初始化

use admin
rs.initiate()

在创建一个用户

 admin> db.createUser({user:"adminUser",pwd:"123456",roles:[{role :"clusterAdmin",db:"admin"}]})

退出出来使用用户登录进去

mongosh -u adminUser-p 123456 --authenticationDatabase admin

进去之后还是要 use admin

然后再
还是老规矩,除了自己

rs.add("192.168.142.156:27017")  // 添加第一个从节点
rs.add("192.168.142.155:27017")  // 添加第二个从节点
rs.add("192.168.142.158:27017")  // 添加第三个从节点

如果你觉得这样子比较麻烦的话,还可以这样操作
第一步:第一次进来先只创建一个用户

mongosh 
use admin
admin> db.createUser({user:"adminUser",pwd:"123456",roles:[{role :"clusterAdmin",db:"admin"}]})

创建完成之后再退出 exit
再次使用创建的用户登录,登陆进去之后

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "192.168.142.157:27017" },
    { _id: 1, host: "192.168.142.156:27017" },
    { _id: 2, host: "192.168.142.155:27017" },
    { _id: 3, host: "192.168.142.158:27017" }
  ]
})

这样子应该也是没问题的,我们查看一下结果

rs.status()
{
  set: 'rs0',
  date: ISODate('2024-10-01T15:38:16.051Z'),
  myState: 1,
  term: Long('1'),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long('2000'),
  majorityVoteCount: 1,
  writeMajorityCount: 1,
  votingMembersCount: 1,
  writableVotingMembersCount: 1,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1727797091, i: 1 }), t: Long('1') },
    lastCommittedWallTime: ISODate('2024-10-01T15:38:11.962Z'),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1727797091, i: 1 }), t: Long('1') },
    appliedOpTime: { ts: Timestamp({ t: 1727797091, i: 1 }), t: Long('1') },
    durableOpTime: { ts: Timestamp({ t: 1727797091, i: 1 }), t: Long('1') },
    lastAppliedWallTime: ISODate('2024-10-01T15:38:11.962Z'),
    lastDurableWallTime: ISODate('2024-10-01T15:38:11.962Z')
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1727797061, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate('2024-10-01T15:21:51.898Z'),
    electionTerm: Long('1'),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1727796111, i: 1 }), t: Long('-1') },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1727796111, i: 1 }), t: Long('-1') },
    numVotesNeeded: 1,
    priorityAtElection: 1,
    electionTimeoutMillis: Long('10000'),
    newTermStartDate: ISODate('2024-10-01T15:21:51.908Z'),
    wMajorityWriteAvailabilityDate: ISODate('2024-10-01T15:21:51.915Z')
  },
  members: [
    {
      _id: 0,
      name: 'master:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 1169,
      optime: { ts: Timestamp({ t: 1727797091, i: 1 }), t: Long('1') },
      optimeDate: ISODate('2024-10-01T15:38:11.000Z'),
      lastAppliedWallTime: ISODate('2024-10-01T15:38:11.962Z'),
      lastDurableWallTime: ISODate('2024-10-01T15:38:11.962Z'),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1727796111, i: 2 }),
      electionDate: ISODate('2024-10-01T15:21:51.000Z'),
      configVersion: 4,
      configTerm: 1,
      self: true,
      lastHeartbeatMessage: ''
    },
    {
      _id: 1,
      name: '192.168.142.156:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T15:38:15.441Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    },
    {
      _id: 2,
      name: '192.168.142.155:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T15:38:15.441Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    },
    {
      _id: 3,
      name: '192.168.142.158:27017',
      health: 0,
      state: 6,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
      optimeDate: ISODate('1970-01-01T00:00:00.000Z'),
      optimeDurableDate: ISODate('1970-01-01T00:00:00.000Z'),
      lastAppliedWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastDurableWallTime: ISODate('1970-01-01T00:00:00.000Z'),
      lastHeartbeat: ISODate('2024-10-01T15:38:15.441Z'),
      lastHeartbeatRecv: ISODate('1970-01-01T00:00:00.000Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      authenticated: false,
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: -1,
      configTerm: -1
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1727797091, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('LDaTTPVX1qNYxZzrNdEZZttnxwQ=', 0),
      keyId: Long('7420827790900985863')
    }
  },
  operationTime: Timestamp({ t: 1727797091, i: 1 })
}

另外,如果要搭建仲裁的话,只需要略微改动一下

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "192.168.142.157:27017", priority: 3 },
    { _id: 1, host: "192.168.142.156:27017" , priority: 2},
    { _id: 2, host: "192.168.142.155:27017" , priority: 1},
    { _id: 3, host: "192.168.142.158:27017", arbiterOnly: true }
  ]
})

或者 rs.add() 替换成 rs.addArb()
你想把哪个节点设置成仲裁,哪个节点的 rs.add 就替换成 rs.addArb 即可

也是不负众望,最后 members 里面所有的节点都添加进来了
那么 两种部署 方式已经演示结束,希望大家能够学会

最后再来总结一下:

副本集的管理

查看副本集

# 查看配置
rs.config()

# 查看副本集状态: 
rs.status()

# 查看master
rs.isMaster()

管理副本集成员

删除成员

  1. 在要删除的成员实例上停止数据库实例
# 登录至指定节点停止实例
rs0:SECONDARY> use admin;
switched to db admin
rs0:SECONDARY> db.shutdownServer()
server should be down...

  1. 在master上执行删除操作
rs0:PRIMARY> rs.remove("10.1.56.85:27017")
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1641217135, 1),
                "signature" : {
                        "hash" : BinData(0,"nhyPvAHXJmE62L0LvIC3J8hAQl8="),
                        "keyId" : NumberLong("7048958896664215556")
                }
        },
        "operationTime" : Timestamp(1641217135, 1)
}
  1. 检查集群是否正常删除
rs.status()

添加成员

  1. 启动mongo并修改相应配置
# /etc/mongod.conf配置文件
security:
  authorization: enabled
  clusterAuthMode: "keyFile"
  keyFile: "/data/mongo/mongodb.key"

replication:
  replSetName: "rs0"
  oplogSizeMB: 5000
  
# 如果之前有数据,记得清理
rm -rf /var/lib/mongo/*

# 启动mongo
systemctl start mongod
  1. 添加成员至副本集
# 在主节点执行以下操作
rs0:PRIMARY> rs.add({host: "10.1.56.85:27017", priority: 0, votes: 0})
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1641217386, 1),
                "signature" : {
                        "hash" : BinData(0,"KLr++3ulixdXPfZhFFAqMhuZuuM="),
                        "keyId" : NumberLong("7048958896664215556")
                }
        },
        "operationTime" : Timestamp(1641217386, 1)
}

  1. 重新配置优先级

    一旦新加入的成员已经过渡到 SECONDARY状态,如果需要的话,使用rs.reconfig()更新新添加的成员priority和votes

rs0:PRIMARY> var cfg=rs.conf();
rs0:PRIMARY> cfg.members[2].priority = 1
1
rs0:PRIMARY> cfg.members[2].votes = 1
1
rs0:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1641217534, 1),
                "signature" : {
                        "hash" : BinData(0,"lj6U6EcieJCS5xJ/eAokxptiNfA="),
                        "keyId" : NumberLong("7048958896664215556")
                }
        },
        "operationTime" : Timestamp(1641217534, 1)
}


以上配置完成后,可以再次通过rs.status()查看集群状态

附录

执行rs.conf()时抛如下异常:

rs0:PRIMARY> rs.conf()
uncaught exception: Error: Could not retrieve replica set config: {
        "ok" : 0,
        "errmsg" : "not authorized on admin to execute command { replSetGetConfig: 1.0, lsid: { id: UUID(\"4a7cd439-f949-41dc-acef-2838267a908a\") }, $clusterTime: { clusterTime: Timestamp(1641214558, 1), signature: { hash: BinData(0, D8E6570EDE34381A0866EB5600A32747FE4BD4DB), keyId: 7048958896664215556 } }, $db: \"admin\" }",
        "code" : 13,
        "codeName" : "Unauthorized",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1641214701, 2),
                "signature" : {
                        "hash" : BinData(0,"y18DwhtkerhqWMwPKLy2m8JXsdk="),
                        "keyId" : NumberLong("7048958896664215556")
                }
        },
        "operationTime" : Timestamp(1641214701, 2)
} :
rs.conf@src/mongo/shell/utils.js:1713:11
@(shell):1:1

原因是当前用户权限不够,需要超级管理员权限:

use admin
db.grantRolesToUser("admin",[{role: "root", db: "admin"}])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2183690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux学习笔记(一):Linux学习环境的安装及远程连接工具的使用

Linux学习笔记&#xff08;一&#xff09;&#xff1a;Linux学习环境的安装及远程连接工具的使用 本地安装虚拟机 1.安装VMWare(点击图片跳转下载&#xff09; 2.安装CentOS7光盘源(点击图片下载&#xff09; 3.安装 一路点下一步 点击确认 等待不要动,可能有点久,直到这个…

【内网渗透】最保姆级的春秋云镜Flarum打靶笔记

目录 flag1 flag3 flag4​ flag2 flag1 扫外网 打的是flarum论坛&#xff0c;p牛之前有写过phar反序列化的利用&#xff1a; 从偶遇Flarum开始的RCE之旅 rockyou.txt爆出administrator/1chris&#xff0c;登录 用这个工具生成phar包 https://github.com/ambionics/p…

【Python报错已解决】IndexError: index 0 is out of bounds for axis 1 with size 0

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

springboot整合seata

一、准备 docker部署seata-server 1.5.2参考&#xff1a;docker安装各个组件的命令 二、springboot集成seata 2.1 引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>&…

helm部署ingress-nginx

helm部署ingress-nginx 19/100 保存草稿 发布文章 sj1163739403 未选择任何文件 ingress-nginx是管理南北向流量很好的一个工具&#xff0c;可以避免在云端频繁对LB进行配置&#xff0c;通过Label也可以实现让ingress-nginx都部署在指定的NodeGroup 一、helm安装ingress-nginx…

数据管理_DM的实现

DataManager 的实现 DataManager 是数据库系统中的核心组件&#xff0c;负责管理底层数据的访问、修改和事务处理。它是 DM 层直接对外提供方法的类&#xff0c;用来对上层其他模块提供数据操作的API的,同时也实现了对 DataItem 对象的缓存管理。DataItem 存储的 key 是由页号…

使用root账号ssh登录虚拟机ubuntu

在C:\Users\Administrator\.ssh目录下的config中&#xff0c;添加ubuntu会在根目录中&#xff0c;建立一个root文件夹。在该文件夹中建一个.ssh目录。像免密登录ubuntu设置中&#xff0c;把公钥考进去。在vscode中打开文件夹中选择要打开的文件夹&#xff0c;就可以不需要在ubu…

fiddler抓包14_自动重定向

课程大纲 重定向&#xff08;Redirect&#xff09;&#xff1a;将网络请求重新定向到其他位置。 按重定向方式分为&#xff1a;网页重定向、域名重定向、接口重定向…… 按持续时间分为&#xff1a;永久重定向、临时重定向。 ① 永久重定向&#xff0c;HTTP 301&#xff08;Mov…

Python或R时偏移算法实现

&#x1f3af;要点 计算单变量或多变量时序距离&#xff0c;使用欧几里得、曼哈顿等函数量化不同时序差异。量化生成时序之间接近度相似性矩阵。使用高尔距离和堪培拉距离等相似度测量。实现最小方差匹配算法&#xff0c;绘制步进模式的图形表示。其他语言包算法实现。 &…

D24【 python 接口自动化学习】- python 基础之判断与循环

day24 while循环 学习日期&#xff1a;20241001 学习目标&#xff1a;判断与循环--34 while循环&#xff1a;需要多次重复执行某段程序时&#xff0c;怎么做&#xff1f; 学习笔记&#xff1a; 循环结构简介 while循环语法 代码实现 循环的退出方法 执行出错&#xff0c;异…

复合系统推文

今天推出的是复合系统协调度这个模型的工具。 参考文献:《“干线公路—城市结点”复合系统协调度分析模型》 复合系统整体协调度模型以协同学的序参量原理和役使原理为基础&#xff0c;模型的参变量选择是模型合理性的前提&#xff0c; 重点选择在整个系统发展演变过程中起主…

CSP-J模拟赛(1)补题报告

前言&#xff1a; 1.交替出场&#xff08;alter) &#xff1a;10 2.翻翻转转&#xff08;filp)&#xff1a;0 3.方格取数&#xff08;square&#xff09;&#xff1a;0 4.圆圆中的方方&#xff08;round)&#xff1a;0 总结一下&#xff1a; 第一次考&#xff0c;没爆零就是胜…

锂电池SOC估计 | Matlab基于BP神经网络的锂电池SOC估计

锂电池SOC估计 | Matlab基于BP神经网络的锂电池SOC估计 目录 锂电池SOC估计 | Matlab基于BP神经网络的锂电池SOC估计预测效果基本描述程序设计参考资料 预测效果 基本描述 锂电池SOC估计 | Matlab基于BP神经网络的锂电池SOC估计 运行环境Matlab2023b及以上。 要实现基于BP神…

鼓组编曲:鼓编写技巧之进鼓加花编写

为了方便快速查阅和运用一些教程笔记&#xff0c;个人记性有时可能不是特别好&#xff0c;所以只能疯狂做笔记了&#xff0c;制作以下图文笔记&#xff0c;仅供参考…… 鼓组加花 鼓的变动 进鼓后然后就可以动次打次了 下面是2个底鼓的加花

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…

SQL第10课挑战题

1. 从OrderItems表中返回每个订单号order_num各有多少行数order_lines&#xff0c;并按order_lines对结果进行排序 2. 返回名为cheapest_item的字段&#xff0c;该字段包含每个供应商成本最低的产品&#xff08;使用products表中的prod_price)&#xff0c;然后从最低成本到最高…

Redis篇(缓存机制 - 基本介绍)(持续更新迭代)

目录 一、缓存介绍 二、经典三缓存问题 1. 缓存穿透 1.1. 简介 1.2. 解决方案 1.3. 总结 2. 缓存雪崩 2.1. 简介 2.2. 解决方案 2.3. 总结 3. 缓存击穿 3.1. 简介 3.2. 解决方案 3.3. 总结 4. 经典三缓存问题出现的根本原因 三、常见双缓存方案 1. 缓存预热 1…

MQ高级:RabbitMQ小细节

在之前的学习中&#xff0c;我们只介绍了消息的发送&#xff0c;但是没有考虑到异常的情况&#xff0c;今天我们就介绍一些异常情况&#xff0c;和细节的部分。 目录 生产者可靠性 生产者重连 生产者确认 MQ可靠性 持久化 Lazy Queue 消费者可靠性 消费者确认机制 失…

LoadRunner实战测试解析:记录一次性能测试过程

环境准备 PC&#xff1a; Windows7/XP LoadRunner11&#xff1a; 与win10及以上版本不兼容 Nmon&#xff1a; 性能监控工具&#xff0c;部署到被测服务器 LoadRunner破解安装 下载地址&#xff1a;https://pan.baidu.com/s/1WJjcFWhrkWW-GgYwXdEniQ 提取码&#xff1a;f4z…

基于Spark的汽车行业大数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…