mongoDB集群

副本集-Replica Sets

MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库当掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载。

副本集角色介绍

副本集有两种类型三种角色

两种类型:

主节点(Primary)类型:数据操作的主要连接点,可读写。

次要(辅助、从)节点(Secondaries)类型:数据冗余备份节点,可以读或选举。

三种角色:

主要成员(Primary):主要接收所有写操作。就是主节点。

副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要配置)。是默认的一种从节点类型。

仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

搭建一主一副本一仲裁

前置

mongodb搭建不需要很多机器,也不需要下载很多遍软件,只需要在启动命令指定对应的conf文件,以及在每个配置文件都设置好对应的db目录和log目录。

博主已经下载好mongodb-linux-x86_64-4.0.10.tgz,并且已经解压并mv mongodb-linux-x86_64-4.0.10 /usr/local/mongodb移动到对应的文件,这样就可以用/usr/local/mongodb/bin/mongod -f /你自己配置文件的地址/ 来启动服务了。

开始搭建

复制代码
# 主
mkdir -p /mongodb/replica_sets/myrs_27017/log \ &
mkdir -p /mongodb/replica_sets/myrs_27017/data/db
# 副本
mkdir -p /mongodb/replica_sets/myrs_27018/log \ &
mkdir -p /mongodb/replica_sets/myrs_27018/data/db
# 仲裁
mkdir -p /mongodb/replica_sets/myrs_27019/log \ &
mkdir -p /mongodb/replica_sets/myrs_27019/data/db

vim /mongodb/replica_sets/myrs_27017/mongod.conf

systemLog:
  # MongoDB发送所有日志输出的目标指定为文件
  destination: file
  # mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/mongodb/replica_sets/myrs_27017/log/mongod.log"
  # 当mongos或mongod实例重新启动时,会将新条目附加到现有日志文件的末尾
  logAppend: true

storage:
  # mongod实例存储其数据的目录,默认值为"/data/db"
  dbPath: "/mongodb/replica_sets/myrs_27017/data/db"
  journal:
    # 启用或禁用持久性日志以确保数据文件保持有效和可恢复
    enabled: true

processManagement:
  # 启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  pidFilePath: "/mongodb/replica_sets/myrs_27017/log/mongod.pid"

net:
  # 服务实例绑定的IP,默认是localhost
  bindIp: "0.0.0.0"
  # 绑定的端口,默认是27017
  port: 27017
replication:
  replSetName: myrs

vim /mongodb/replica_sets/myrs_27018/mongod.conf


systemLog:
  # MongoDB发送所有日志输出的目标指定为文件
  destination: file
  # mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/mongodb/replica_sets/myrs_27018/log/mongod.log"
  # 当mongos或mongod实例重新启动时,会将新条目附加到现有日志文件的末尾
  logAppend: true

storage:
  # mongod实例存储其数据的目录,默认值为"/data/db"
  dbPath: "/mongodb/replica_sets/myrs_27018/data/db"
  journal:
    # 启用或禁用持久性日志以确保数据文件保持有效和可恢复
    enabled: true

processManagement:
  # 启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  pidFilePath: "/mongodb/replica_sets/myrs_27018/log/mongod.pid"

net:
  # 服务实例绑定的IP,默认是localhost
  bindIp: "0.0.0.0"
  # 绑定的端口,默认是27017
  port: 27018
replication:
  replSetName: myrs





vim /mongodb/replica_sets/myrs_27019/mongod.conf



systemLog:
  # MongoDB发送所有日志输出的目标指定为文件
  destination: file
  # mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/mongodb/replica_sets/myrs_27019/log/mongod.log"
  # 当mongos或mongod实例重新启动时,会将新条目附加到现有日志文件的末尾
  logAppend: true

storage:
  # mongod实例存储其数据的目录,默认值为"/data/db"
  dbPath: "/mongodb/replica_sets/myrs_27019/data/db"
  journal:
    # 启用或禁用持久性日志以确保数据文件保持有效和可恢复
    enabled: true

processManagement:
  # 启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  pidFilePath: "/mongodb/replica_sets/myrs_27019/log/mongod.pid"

net:
  # 服务实例绑定的IP,默认是localhost
  bindIp: "0.0.0.0"
  # 绑定的端口,默认是27017
  port: 27019
replication:
  replSetName: myrs

启动

复制代码
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf

/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf

/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf

初始化配置副本集和主节点

连接和初始化

这个集群不是搭建好就能用的,还需要连接上去做配置

复制代码
/usr/local/mongodb/bin/mongo  --port=27017

# 连接上之后,很多命令都不能使用,比如,show dbs等,必须初始化

# 初始化
rs.initiate()

1)"ok"的值为1,说明创建成功。

2)命令行提示符发生变化,变成了一个从节点角色,此时默认不能读写。稍等片刻,回车,变成主节点。

复制代码
# 查看当前副本集的配置内容
rs.conf()
rs.config()

{
        "_id" : "myrs",
        "version" : 1,
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "VM-109-112-tencentos:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
        "settings" : {
                "chainingAllowed" : true,
                "heartbeatIntervalMillis" : 2000,
                "heartbeatTimeoutSecs" : 10,
                "electionTimeoutMillis" : 10000,
                "catchUpTimeoutMillis" : -1,
                "catchUpTakeoverDelayMillis" : 30000,
                "getLastErrorModes" : {

                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                },
                "replicaSetId" : ObjectId("687792d02d18d0cf71477f3f")
        }
}

说明:

1)"_id" : "myrs":副本集的配置数据存储的主键值,默认就是副本集的名字

2)"members":副本集成员数组,此时只有一个:"host" : "180.76.159.126:27017",该成员不

是仲裁节点:"arbiterOnly" : false,优先级(权重值):"priority" : 1,

3)"settings":副本集的参数配置。

提示:副本集配置的查看命令,本质是查询的是 system.replset的表中的数据:

复制代码
use local

show collections

db.system.replset.find()


{ "_id" : "myrs", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "VM-109-112-tencentos:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : {  }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("687792d02d18d0cf71477f3f") } }
查看集群状态
复制代码
rs.status()

{
        "set" : "myrs",
        "date" : ISODate("2025-07-16T11:58:32.762Z"),
        "myState" : 1,
        "term" : NumberLong(1),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1752667104, 1),
                        "t" : NumberLong(1)
                },
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1752667104, 1),
                        "t" : NumberLong(1)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1752667104, 1),
                        "t" : NumberLong(1)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1752667104, 1),
                        "t" : NumberLong(1)
                }
        },
        "lastStableCheckpointTimestamp" : Timestamp(1752667074, 1),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "VM-109-112-tencentos:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 327,
                        "optime" : {
                                "ts" : Timestamp(1752667104, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2025-07-16T11:58:24Z"),
                        "syncingTo" : "",
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1752666832, 2),
                        "electionDate" : ISODate("2025-07-16T11:53:52Z"),
                        "configVersion" : 1,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1752667104, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1752667104, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

说明:

1)"set" : "myrs":副本集的名字

2)"myState": 1:说明状态正常

3)"members":副本集成员数组,此时只有一个:"name" :"VM-109-112-tencentos",该成员的

角色是"stateStr" : "PRIMARY",该节点是健康的:"health" : 1。

添加从节点
复制代码
rs.add("21.91.109.112:27018")

{
        "ok" : 1,
        "operationTime" : Timestamp(1752667344, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1752667344, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

1)"ok" : 1:说明添加成功。

这样添加的是副本节点,添加仲裁节点看下边

添加仲裁节点
复制代码
rs.add("21.91.109.112:27019",arbiterOnly)
或者
rs.addArb("21.91.109.112:27019")


{
        "ok" : 1,
        "operationTime" : Timestamp(1752667477, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1752667477, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

这样运行完之后就搭建完成了,可以通过rs.status()命令来查看集群状态或者rs.config()来查看集群的配置信息。

副本集的数据操作

登陆主节点,对主节点进行插入数据。

复制代码
/usr/local/mongodb/bin/mongo  --port 27017


use articledb
switched to db articledb
myrs:PRIMARY> db
articledb


db.comment.insert({
    "articleid": "100000",
    "content": "今天天气真好,阳光\n明媚",
    "userid": "1001",
    "nickname": "Rose",
    "createdatetime": new Date()
});

然后登陆从节点,尝试查看或插入数据

复制代码
/usr/local/mongodb/bin/mongo  --port 27018


show dbs
2025-07-17T10:02:51.190+0800 E QUERY    [js] Error: listDatabases failed:{
        "operationTime" : Timestamp(1752717765, 1),
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotMasterNoSlaveOk",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1752717765, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:139:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1

发现,不能读取集合的数据。当前从节点只是一个备份,不是奴隶节点,无法读取数据,写当然更不行。

因为默认情况下,从节点是没有读写权限的,可以增加读的权限,但需要进行设置。

复制代码
rs.slaveOk()
或
rs.slaveOk(true)

该命令是 db.getMongo().setSlaveOk()的简化命令。

此时执行查询命令,成功。

此时在从节点进行插入,发现失败

复制代码
db.comment.insert({
    "_id": "1",
    "articleid": "100001",
    "content": "我们\n不应该把清晨浪费在手机上,健康很重要,k一杯温水幸福你我\n他。",
    "userid": "1002",
    "nickname": "相忘于江湖",
    "createdatetime": new Date("2019-08-05T22:08:15.522Z"),
    "likenum": NumberInt(1000),
    "state": "1"
});



WriteCommandError({
        "operationTime" : Timestamp(1752718015, 1),
        "ok" : 0,
        "errmsg" : "not master",
        "code" : 10107,
        "codeName" : "NotMaster",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1752718015, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
})

现在可实现了读写分离,让主插入数据,让从来读取数据。

如果要取消作为奴隶节点的读权限:

复制代码
rs.slaveOk(false)

仲裁者节点,不存放任何业务数据的,可以登录查看

复制代码
/usr/local/mongodb/bin/mongo  --port 27019
相关推荐
dexianshen15 分钟前
Linux中的数据库操作基础
数据库
城里有一颗星星44 分钟前
7.事务操作
数据库·mysql·goland
言之。1 小时前
Django中get()与filter()对比
数据库·django·sqlite
RoundLet_Y1 小时前
【知识图谱】Neo4j桌面版运行不起来怎么办?Neo4j Desktop无法打开!
数据库·python·知识图谱·neo4j
代码老y2 小时前
从单线程到云原生:Redis 二十年演进全景与内在机理深剖
数据库·redis·云原生
轩宇^_^2 小时前
Qt CMake 学习文档
数据库·qt·学习
眠りたいです3 小时前
MySQL的索引操作及底层结构浅析
linux·数据库·c++·mysql
Liquad Li3 小时前
AI 优化快消品生产调度:提升效率与响应速度的关键路径
服务器·数据库·人工智能
满分观察网友z3 小时前
MySQL 分页的“灵异事件”:为什么我的排序总是不对劲?
数据库
时空无限4 小时前
ubuntu 22.04 pam 模块设置用户登录失败锁定
linux·数据库·ubuntu