集群类型

  • 单机模式:一台机器对外提供服务;
  • 集群模式:多台机器对外提供同一服务;
  • 伪集群模式:单台机器上启动多个实例,模拟多机器场景对外提供服务。

规划

image

操作系统节点IP端口作用Mongo版本数据目录日志目录配置目录
rocky9.4192.168.0.23827017主节点8.0.1/data/mongo/data/data/mongo/logs/data/mongo/conf
rocky9.4192.168.0.23927017副本节点8.0.1/data/mongo/data/data/mongo/logs/data/mongo/conf
rocky9.4192.168.0.24027017仲裁节点8.0.1/data/mongo/data/data/mongo/logs/data/mongo/conf

搭建

  1. 所有节点均需执行:

    mkdir /data/mongo/{data,logs,conf} -p
    dnf install libcurl openssl xz-libs
    cd /usr/local/src
    wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel93-8.0.1.tgz
    tar xzvf mongodb-linux-x86_64-rhel93-8.0.1.tgz
    cd mongodb-linux-x86_64-rhel93-8.0.1
    cp bin/{mongod,mongos} /usr/local/bin/
    
  2. 主节点配置文件准备:

    # 主节点操作
    vim /data/mongo/conf/mongo-master.conf
    # MongoDB日志存储相关配置
    systemLog:
        # 将所有日志写到指定文件中
        destination: file
        # 记录所有日志信息的文件路径
        path: "/data/mongo/logs/mongo.log"
        # 当服务重启时,将新日志以追加形式写到现有日志尾部
        logAppend: true
    storage:
        # 指定MongoDB存储数据的目录
        dbPath: "/data/mongo/data"
    processManagement:
        # 以后台进程方式运行MongoDB服务
        fork: true
        # 指定保存mongo进程ID的文件位置
        pidFilePath: "/data/mongo/mongo.pid"
    net:
        # 绑定服务实例的IP,默认是localhost,这里换成本机IP
        bindIp: 192.168.0.238
        #绑定的端口,默认是27017
        port: 27017
    replication:
        # 指定副本集群的名称
        replSetName: mongo-set
    
  3. 启动主节点服务

    # 主节点操作
    mongod -f /data/mongo/conf/mongo-master.conf
    # 这里死活执行不成功,报Illegal instruction (core dumped),更换7.0.15 8.0.3版本均无效,原因为mongo5.x后需要avx指令集,查询cpu后发现支持,
    # 但pve虚拟化默认为x86-64-v2-AES模式,此模式默认不会将新的指令集开放给虚拟机。需要关闭虚拟机对cpu模式进行修改,修改为host模式。
    
    # 查看端口是否被监听
    netstat -lanp | grep 27017
    
    echo 'mongod -f /data/mongo/conf/mongo-master.conf' >> /etc/rc.local
    
  4. 从节点配置文件准备

    # 从节点操作
    vim /data/mongo/conf/mongo-slave.conf
    # MongoDB日志存储相关配置
    systemLog:
        # 将所有日志写到指定文件中
        destination: file
        # 记录所有日志信息的文件路径
        path: "/data/mongo/logs/mongo.log"
        # 当服务重启时,将新日志以追加形式写到现有日志尾部
        logAppend: true
    storage:
        # 指定MongoDB存储数据的目录
        dbPath: "/data/mongo/data"
    processManagement:
        # 以后台进程方式运行MongoDB服务
        fork: true
        # 指定保存mongo进程ID的文件位置
        pidFilePath: "/data/mongo/mongo.pid"
    net:
        # 绑定服务实例的IP,默认是localhost,这里换成本机IP
        bindIp: 192.168.0.239
        #绑定的端口,默认是27017
        port: 27017
    replication:
        # 指定副本集群的名称
        replSetName: mongo-set
    
  5. 启动从节点服务

    # 从节点操作
    mongod -f /data/mongo/conf/mongo-slave.conf
    
    # 查看端口是否被监听
    netstat -lanp | grep 27017
    
    echo 'mongod -f /data/mongo/conf/mongo-slave.conf' >> /etc/rc.local
    
  6. 仲裁节点配置文件准备

    # 仲裁节点操作
    vim /data/mongo/conf/mongo-arbit.conf
    # MongoDB日志存储相关配置
    systemLog:
        # 将所有日志写到指定文件中
        destination: file
        # 记录所有日志信息的文件路径
        path: "/data/mongo/logs/mongo.log"
        # 当服务重启时,将新日志以追加形式写到现有日志尾部
        logAppend: true
    storage:
        # 指定MongoDB存储数据的目录
        dbPath: "/data/mongo/data"
    processManagement:
        # 以后台进程方式运行MongoDB服务
        fork: true
        # 指定保存mongo进程ID的文件位置
        pidFilePath: "/data/mongo/mongo.pid"
    net:
        # 绑定服务实例的IP,默认是localhost,这里换成本机IP
        bindIp: 192.168.0.240
        #绑定的端口,默认是27017
        port: 27017
    replication:
        # 指定副本集群的名称
        replSetName: mongo-set
    
  7. 启动仲裁节点服务

    # 从节点操作
    mongod -f /data/mongo/conf/mongo-arbit.conf
    
    # 查看端口是否被监听
    netstat -lanp | grep 27017
    
    echo 'mongod -f /data/mongo/conf/mongo-arbit.conf' >> /etc/rc.local
    
  8. 初始化
    通过mongosh客户端工具连接主节点,初始化副本集群

    # 主节点操作
    wget https://downloads.mongodb.com/compass/mongosh-2.3.3-linux-x64.tgz
    tar xzvf mongosh-2.3.3-linux-x64.tgz
    cd mongosh-2.3.3-linux-x64/bin
    
    
    [root@rocky238 bin]# ./mongosh 192.168.0.238:27017
    Current Mongosh Log ID:	67370968a68cd32f6dc1c18b
    Connecting to:		mongodb://192.168.0.238:27017/?directConnection=true&appName=mongosh+2.3.3
    Using MongoDB:		8.0.1
    Using Mongosh:		2.3.3
    
    For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
    
    
    To help improve our products, anonymous usage data is collected and sent to MongoDB periodically (https://www.mongodb.com/legal/privacy-policy).
    You can opt-out by running the disableTelemetry() command.
    
    ------
       The server generated these startup warnings when booting
       2024-11-15T16:06:51.332+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
       2024-11-15T16:06:51.332+08:00: You are running this process as the root user, which is not recommended
       2024-11-15T16:06:51.332+08:00: Soft rlimits for open file descriptors too low
       2024-11-15T16:06:51.332+08:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
       2024-11-15T16:06:51.332+08:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
       2024-11-15T16:06:51.332+08:00: We suggest setting the contents of sysfsFile to 0.
       2024-11-15T16:06:51.332+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
       2024-11-15T16:06:51.332+08:00: We suggest setting swappiness to 0 or 1, as swapping can cause performance problems.
    ------
    
    test> rs.initiate();
    {
      info2: 'no configuration specified. Using a default configuration for the set',
      me: '192.168.0.238:27017',
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660169, i: 1 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660169, i: 1 })
    }
    # 添加从节点
    mongo-set [direct: secondary] test> rs.add("192.168.0.239:27017")
    {
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660268, i: 1 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660268, i: 1 })
    }
    # 修改写关注级别
    mongo-set [direct: primary] test> db.adminCommand({
    ... "setDefaultRWConcern" : 1,
    ... "defaultWriteConcern" : {
    ... "w" : "majority"
    ... }
    ... });
    {
      defaultReadConcern: { level: 'local' },
      defaultWriteConcern: { w: 'majority', wtimeout: 0 },
      updateOpTime: Timestamp({ t: 1731660359, i: 1 }),
      updateWallClockTime: ISODate('2024-11-15T08:46:04.016Z'),
      defaultWriteConcernSource: 'global',
      defaultReadConcernSource: 'implicit',
      localUpdateWallClockTime: ISODate('2024-11-15T08:46:04.032Z'),
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660364, i: 2 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660364, i: 2 })
    }
    # 添加仲裁节点
    mongo-set [direct: primary] test> rs.addArb("192.168.0.240:27017")
    {
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660394, i: 1 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660394, i: 1 })
    }
    
    # 查看集群状态
    mongo-set [direct: primary] test> rs.conf()
    {
      _id: 'mongo-set',
      version: 4,
      term: 1,
      members: [
        {
          _id: 0,
          host: '192.168.0.238:27017',
          arbiterOnly: false,
          buildIndexes: true,
          hidden: false,
          priority: 1,
          tags: {},
          secondaryDelaySecs: Long('0'),
          votes: 1
        },
        {
          _id: 1,
          host: '192.168.0.239:27017',
          arbiterOnly: false,
          buildIndexes: true,
          hidden: false,
          priority: 1,
          tags: {},
          secondaryDelaySecs: Long('0'),
          votes: 1
        },
        {
          _id: 2,
          host: '192.168.0.240:27017',
          arbiterOnly: true,
          buildIndexes: true,
          hidden: false,
          priority: 0,
          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('6737098922b6337a0182820d')
      }
    }
    mongo-set [direct: primary] test> rs.status()
    {
      set: 'mongo-set',
      date: ISODate('2024-11-15T08:47:56.103Z'),
      myState: 1,
      term: Long('1'),
      syncSourceHost: '',
      syncSourceId: -1,
      heartbeatIntervalMillis: Long('2000'),
      majorityVoteCount: 2,
      writeMajorityCount: 2,
      votingMembersCount: 3,
      writableVotingMembersCount: 2,
      optimes: {
        lastCommittedOpTime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
        lastCommittedWallTime: ISODate('2024-11-15T08:47:49.824Z'),
        readConcernMajorityOpTime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
        appliedOpTime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
        durableOpTime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
        writtenOpTime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
        lastAppliedWallTime: ISODate('2024-11-15T08:47:49.824Z'),
        lastDurableWallTime: ISODate('2024-11-15T08:47:49.824Z'),
        lastWrittenWallTime: ISODate('2024-11-15T08:47:49.824Z')
      },
      lastStableRecoveryTimestamp: Timestamp({ t: 1731660469, i: 1 }),
      electionCandidateMetrics: {
        lastElectionReason: 'electionTimeout',
        lastElectionDate: ISODate('2024-11-15T08:42:49.770Z'),
        electionTerm: Long('1'),
        lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1731660169, i: 1 }), t: Long('-1') },
        lastSeenWrittenOpTimeAtElection: { ts: Timestamp({ t: 1731660169, i: 1 }), t: Long('-1') },
        lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1731660169, i: 1 }), t: Long('-1') },
        numVotesNeeded: 1,
        priorityAtElection: 1,
        electionTimeoutMillis: Long('10000'),
        newTermStartDate: ISODate('2024-11-15T08:42:49.805Z'),
        wMajorityWriteAvailabilityDate: ISODate('2024-11-15T08:42:49.877Z')
      },
      members: [
        {
          _id: 0,
          name: '192.168.0.238:27017',
          health: 1,
          state: 1,
          stateStr: 'PRIMARY',
          uptime: 2466,
          optime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
          optimeDate: ISODate('2024-11-15T08:47:49.000Z'),
          optimeWritten: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
          optimeWrittenDate: ISODate('2024-11-15T08:47:49.000Z'),
          lastAppliedWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          lastDurableWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          lastWrittenWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          syncSourceHost: '',
          syncSourceId: -1,
          infoMessage: '',
          electionTime: Timestamp({ t: 1731660169, i: 2 }),
          electionDate: ISODate('2024-11-15T08:42:49.000Z'),
          configVersion: 4,
          configTerm: 1,
          self: true,
          lastHeartbeatMessage: ''
        },
        {
          _id: 1,
          name: '192.168.0.239:27017',
          health: 1,
          state: 2,
          stateStr: 'SECONDARY',
          uptime: 207,
          optime: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
          optimeDurable: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
          optimeWritten: { ts: Timestamp({ t: 1731660469, i: 1 }), t: Long('1') },
          optimeDate: ISODate('2024-11-15T08:47:49.000Z'),
          optimeDurableDate: ISODate('2024-11-15T08:47:49.000Z'),
          optimeWrittenDate: ISODate('2024-11-15T08:47:49.000Z'),
          lastAppliedWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          lastDurableWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          lastWrittenWallTime: ISODate('2024-11-15T08:47:49.824Z'),
          lastHeartbeat: ISODate('2024-11-15T08:47:54.476Z'),
          lastHeartbeatRecv: ISODate('2024-11-15T08:47:54.475Z'),
          pingMs: Long('0'),
          lastHeartbeatMessage: '',
          syncSourceHost: '192.168.0.238:27017',
          syncSourceId: 0,
          infoMessage: '',
          configVersion: 4,
          configTerm: 1
        },
        {
          _id: 2,
          name: '192.168.0.240:27017',
          health: 1,
          state: 7,
          stateStr: 'ARBITER',
          uptime: 81,
          lastHeartbeat: ISODate('2024-11-15T08:47:54.489Z'),
          lastHeartbeatRecv: ISODate('2024-11-15T08:47:54.490Z'),
          pingMs: Long('0'),
          lastHeartbeatMessage: '',
          syncSourceHost: '',
          syncSourceId: -1,
          infoMessage: '',
          configVersion: 4,
          configTerm: 1
        }
      ],
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660469, i: 1 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660469, i: 1 })
    }
    
    
  9. 账号密码配置

    需要开启认证权限控制:用于自管理部署的运行时数据库配置 - MongoDB 手册 v8.0

    mongo-set [direct: primary] test> use admin;
    switched to db admin
    mongo-set [direct: primary] admin> db.createUser({"user":"root", "pwd":"YOUR_PASSWORD", "roles":["root"]});
    {
      ok: 1,
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1731660809, i: 5 }),
        signature: {
          hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
          keyId: Long('0')
        }
      },
      operationTime: Timestamp({ t: 1731660809, i: 5 })
    }
    

星霜荏苒 居诸不息