专业网站制作设计公司哪家好/建设网站
一、副本集 Replica Sets
1.1 简介
MongoDB 中的副本集(Replica Set)是一组维护相同数据集的 mongod 服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。
也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库 down 掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载。
1):冗余和数据可用性
复制提供冗余并提高数据可用性。 通过在不同数据库服务器上提供多个数据副本,复制可提供一定级别的容错功能,以防止丢失单个数据库服务器。
在某些情况下,复制可以提供增加的读取性能,因为客户端可以将读取操作发送到不同的服务上, 在不同数据中心维护数据副本可以增加分布式应用程序的数据位置和可用性。 您还可以为专用目的维护其他副本,例如灾难恢复,报告或备份。
2):MongoDB 中的复制
副本集是一组维护相同数据集的 mongod 实例。 副本集包含多个数据承载节点和可选的一个仲裁节点。在承载数据的节点中,一个且仅一个成员被视为主节点,而其他节点被视为次要(从)节点。
主节点接收所有写操作。 副本集只能有一个主要的写入; 虽然在某些情况下,另一个 mongod 实例可能暂时认为自己也是主要的。主要记录其操作日志中的数据集的所有更改,即 oplog。
辅助(副本)节点复制主节点的 oplog 并将操作应用于其数据集,以使辅助节点的数据集反映主节点的数据集。 如果主要人员不在,则符合条件的中学将举行选举以选出新的主要人员。
3):主从复制和副本集区别
主从集群和副本集最大的区别就是副本集没有固定的 “主节点”;整个集群会选出一个“主节点”,当其挂掉后,又在剩下的从节点中选中其他节点为 “主节点”,副本集总有一个活跃点(主、primary) 和一个或多个备份节点 (从、secondary)。
1.2 副本集三个角色
副本集有两种类型三种角色。
两种类型:
主节点(Primary)类型:数据操作的主要连接点,可读写。
次要(辅助、从)节点(Secondaries)类型:数据冗余备份节点,可以读或选举。
三种角色:
主要成员(Primary):主要接收所有写操作。就是主节点。
副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要配置)。是默认的一种从节点类型。
仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。
关于仲裁者的额外说明:
您可以将额外的 mongod 实例添加到副本集作为仲裁者。 仲裁者不维护数据集。 仲裁者的目的是通过响应其他副本集成员的心跳和选举请求来维护副本集中的仲裁。 因为它们不存储数据集,所以仲裁器可以是提供副本集仲裁功能的好方法,其资源成本比具有数据集的全功能副本集成员更便宜。
如果您的副本集具有偶数个成员,请添加仲裁者以获得主要选举中的“大多数”投票。 仲裁者不需要专用硬件。
仲裁者将永远是仲裁者,而主要人员可能会退出并成为次要人员,而次要人员可能成为选举期间的主要人员。
如果你的副本+主节点的个数是偶数,建议加一个仲裁者,形成奇数,容易满足大多数的投票。
如果你的副本+主节点的个数是奇数,可以不加仲裁者。
1.3 副本集架构目标
一主一副本一仲裁,架构图如下所示:
1.4 副本集的创建
1.4.1 创建主节点
建立存放数据和日志的目录
# 存放日志信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27017/log# 存放数据信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27017/data/db
新建配置信息
vim /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
内容如下:
systemLog:# MongoDB发送所有日志输出的目标指定为文件destination: file# mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径path: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.log"# 当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。logAppend: true
storage:# mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。dbPath: "/usr/local/mongodb/replica_sets/myrs_27017/data/db"journal:# 启用或禁用持久性日志以确保数据文件保持有效和可恢复。enabled: true
processManagement:# 启用在后台运行mongos或mongod进程的守护进程模式。fork: true# 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PIDpidFilePath: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.pid"
net:# 服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip#bindIpAll: true# 服务实例绑定的IPbindIp: localhost,192.168.229.154#bindIp# 绑定的端口port: 27017
replication:# 副本集的名称replSetName: myrs
启动节点服务:
[root@node1 mongodb]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 42243
child process started successfully, parent exiting
1.4.2 创建副本节点
建立存放数据和日志的目录
# 存放日志信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27018/log# 存放数据信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27018/data/db
新建配置信息
vim /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
内容如下:
systemLog:# MongoDB发送所有日志输出的目标指定为文件destination: file# mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径path: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.log"# 当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。logAppend: true
storage:# mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。dbPath: "/usr/local/mongodb/replica_sets/myrs_27018/data/db"journal:# 启用或禁用持久性日志以确保数据文件保持有效和可恢复。enabled: true
processManagement:# 启用在后台运行mongos或mongod进程的守护进程模式。fork: true# 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PIDpidFilePath: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.pid"
net:# 服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip#bindIpAll: true# 服务实例绑定的IPbindIp: localhost,192.168.229.154#bindIp# 绑定的端口port: 27018
replication:# 副本集的名称replSetName: myrs
启动节点服务:
[root@node1 mongodb]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 45029
child process started successfully, parent exiting
1.4.3 创建仲裁节点
建立存放数据和日志的目录
# 存放日志信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27019/log# 存放数据信息
mkdir -p /usr/local/mongodb/replica_sets/myrs_27019/data/db
新建配置信息
vim /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
内容如下:
systemLog:# MongoDB发送所有日志输出的目标指定为文件destination: file# mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径path: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.log"# 当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。logAppend: true
storage:# mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。dbPath: "/usr/local/mongodb/replica_sets/myrs_27019/data/db"journal:# 启用或禁用持久性日志以确保数据文件保持有效和可恢复。enabled: true
processManagement:# 启用在后台运行mongos或mongod进程的守护进程模式。fork: true# 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PIDpidFilePath: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.pid"
net:# 服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip#bindIpAll: true# 服务实例绑定的IPbindIp: localhost,192.168.229.154#bindIp# 绑定的端口port: 27019
replication:# 副本集的名称replSetName: myrs
启动节点服务:
[root@node1 mongodb]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 46093
child process started successfully, parent exiting
1.4.4 初始化配置副本集和主节点
使用客户端命令连接任意一个节点,但这里尽量要连接主节点 (27017节点):
/usr/local/mongodb/bin/mongo --host=192.168.229.154 --port=27017
结果,连接上之后,很多命令无法使用,比如 show dbs 等,如下所示,必须初始化副本集才可以。
# 使用默认的配置来初始化副本集
rs.initiate()
# "ok":1,说明创建成功。
# 命令行提示符发生变化,变成了一个从节点角色,此时默认不能读写。稍等片刻,回车,变成主节点。
> rs.initiate()
{"info2" : "no configuration specified. Using a default configuration for the set","me" : "192.168.229.154:27017","ok" : 1
}
myrs:SECONDARY>
myrs:PRIMARY>
1.4.5 查看副本集的配置内容
查看当前副本集配置的文档,语法如下:
# rs.config() 是该方法的别名。
# configuration:可选,如果没有配置,则使用默认主节点配置
rs.conf(configuration)
在 27017 上执行副本集中当前节点的默认节点配置,如下:
myrs:PRIMARY> rs.conf()
{# 副本集的配置数据存储的主键值,默认就是副本集的名字"_id" : "myrs","version" : 1,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,# 副本集成员数组,此时只有一个: "host" : "192.168.229.154:27017" "members" : [{"_id" : 0,"host" : "192.168.229.154: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("6528b761af0089c47768dd07")}
}
提示:
副本集配置的查看命令,本质是查询的是 system.replset 的表中的数据
myrs:PRIMARY> use local
switched to db local
myrs:PRIMARY> show collections
oplog.rs
replset.election
replset.minvalid
replset.oplogTruncateAfterPoint
startup_log
system.replset
system.rollback.id
myrs:PRIMARY> db.system.replset.find()
{ "_id" : "myrs", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "192.168.229.154: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("6528b761af0089c47768dd07") } }
myrs:PRIMARY>
1.4.6 查看副本集状态
返回包含状态信息的文档。此输出使用从副本集的其他成员发送的心跳包中获得的数据反映副本集的当前状态。语法如下:
rs.status()
# 在 27017 上查看副本集状态
myrs:PRIMARY> rs.status()
{# 副本集的名字"set" : "myrs","date" : ISODate("2023-10-13T06:33:05.838Z"),# 说明状态正常"myState" : 1,"term" : NumberLong(1),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1697178781, 1),"t" : NumberLong(1)},"readConcernMajorityOpTime" : {"ts" : Timestamp(1697178781, 1),"t" : NumberLong(1)},"appliedOpTime" : {"ts" : Timestamp(1697178781, 1),"t" : NumberLong(1)},"durableOpTime" : {"ts" : Timestamp(1697178781, 1),"t" : NumberLong(1)}},"lastStableCheckpointTimestamp" : Timestamp(1697178721, 1),"electionCandidateMetrics" : {"lastElectionReason" : "electionTimeout","lastElectionDate" : ISODate("2023-10-13T03:20:02.154Z"),"electionTerm" : NumberLong(1),"lastCommittedOpTimeAtElection" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"lastSeenOpTimeAtElection" : {"ts" : Timestamp(1697167201, 1),"t" : NumberLong(-1)},"numVotesNeeded" : 1,"priorityAtElection" : 1,"electionTimeoutMillis" : NumberLong(10000),"newTermStartDate" : ISODate("2023-10-13T03:20:02.231Z"),"wMajorityWriteAvailabilityDate" : ISODate("2023-10-13T03:20:02.308Z")},# 副本集成员数组,此时只有一个"members" : [{"_id" : 0,"name" : "192.168.229.154:27017",# 该节点是健康的"health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 12350,"optime" : {"ts" : Timestamp(1697178781, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2023-10-13T06:33:01Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1697167202, 1),"electionDate" : ISODate("2023-10-13T03:20:02Z"),"configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""}],"ok" : 1,"operationTime" : Timestamp(1697178781, 1),"$clusterTime" : {"clusterTime" : Timestamp(1697178781, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
1.4.7 添加副本从节点
在主节点添加从节点,将其他成员加入到副本集,语法如下:
# host格式为:ip地址:端口号
rs.add(host)
将 27018 的副本节点添加到副本集中,命令如下:
myrs:PRIMARY> rs.add("192.168.229.154:27018")
{# 说明添加成功"ok" : 1,"operationTime" : Timestamp(1697179246, 1),"$clusterTime" : {"clusterTime" : Timestamp(1697179246, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
此时,再次查看副本集状态
myrs:PRIMARY> rs.status()
{"set" : "myrs","date" : ISODate("2023-10-13T06:41:58.219Z"),"myState" : 1,"term" : NumberLong(1),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"readConcernMajorityOpTime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"appliedOpTime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"durableOpTime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)}},"lastStableCheckpointTimestamp" : Timestamp(1697179262, 1),"electionCandidateMetrics" : {"lastElectionReason" : "electionTimeout","lastElectionDate" : ISODate("2023-10-13T03:20:02.154Z"),"electionTerm" : NumberLong(1),"lastCommittedOpTimeAtElection" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"lastSeenOpTimeAtElection" : {"ts" : Timestamp(1697167201, 1),"t" : NumberLong(-1)},"numVotesNeeded" : 1,"priorityAtElection" : 1,"electionTimeoutMillis" : NumberLong(10000),"newTermStartDate" : ISODate("2023-10-13T03:20:02.231Z"),"wMajorityWriteAvailabilityDate" : ISODate("2023-10-13T03:20:02.308Z")},"members" : [{"_id" : 0,"name" : "192.168.229.154:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 12883,"optime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2023-10-13T06:41:52Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1697167202, 1),"electionDate" : ISODate("2023-10-13T03:20:02Z"),"configVersion" : 2,"self" : true,"lastHeartbeatMessage" : ""},# 这个新创建的第二个角色{"_id" : 1,"name" : "192.168.229.154:27018","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 71,"optime" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1697179312, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2023-10-13T06:41:52Z"),"optimeDurableDate" : ISODate("2023-10-13T06:41:52Z"),"lastHeartbeat" : ISODate("2023-10-13T06:41:56.894Z"),"lastHeartbeatRecv" : ISODate("2023-10-13T06:41:57.236Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.229.154:27017","syncSourceHost" : "192.168.229.154:27017","syncSourceId" : 0,"infoMessage" : "","configVersion" : 2}],"ok" : 1,"operationTime" : Timestamp(1697179312, 1),"$clusterTime" : {"clusterTime" : Timestamp(1697179312, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
1.4.8 添加仲裁从节点
添加一个仲裁节点到副本集,语法如下:
rs.addArb(host)
将 27019 的仲裁节点添加到副本集中
myrs:PRIMARY> rs.addArb("192.168.229.154:27019")
{# 说明添加成功"ok" : 1,"operationTime" : Timestamp(1697179436, 1),"$clusterTime" : {"clusterTime" : Timestamp(1697179436, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
此时,再次查看副本集状态
myrs:PRIMARY> rs.status()
{"set" : "myrs","date" : ISODate("2023-10-13T06:45:08.595Z"),"myState" : 1,"term" : NumberLong(1),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"readConcernMajorityOpTime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"appliedOpTime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"durableOpTime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)}},"lastStableCheckpointTimestamp" : Timestamp(1697179436, 1),"electionCandidateMetrics" : {"lastElectionReason" : "electionTimeout","lastElectionDate" : ISODate("2023-10-13T03:20:02.154Z"),"electionTerm" : NumberLong(1),"lastCommittedOpTimeAtElection" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"lastSeenOpTimeAtElection" : {"ts" : Timestamp(1697167201, 1),"t" : NumberLong(-1)},"numVotesNeeded" : 1,"priorityAtElection" : 1,"electionTimeoutMillis" : NumberLong(10000),"newTermStartDate" : ISODate("2023-10-13T03:20:02.231Z"),"wMajorityWriteAvailabilityDate" : ISODate("2023-10-13T03:20:02.308Z")},"members" : [{"_id" : 0,"name" : "192.168.229.154:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 13073,"optime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2023-10-13T06:45:02Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1697167202, 1),"electionDate" : ISODate("2023-10-13T03:20:02Z"),"configVersion" : 3,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "192.168.229.154:27018","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 262,"optime" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1697179502, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2023-10-13T06:45:02Z"),"optimeDurableDate" : ISODate("2023-10-13T06:45:02Z"),"lastHeartbeat" : ISODate("2023-10-13T06:45:06.956Z"),"lastHeartbeatRecv" : ISODate("2023-10-13T06:45:06.973Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.229.154:27017","syncSourceHost" : "192.168.229.154:27017","syncSourceId" : 0,"infoMessage" : "","configVersion" : 3},{"_id" : 2,"name" : "192.168.229.154:27019","health" : 1,"state" : 7,"stateStr" : "ARBITER","uptime" : 71,"lastHeartbeat" : ISODate("2023-10-13T06:45:06.955Z"),"lastHeartbeatRecv" : ISODate("2023-10-13T06:45:06.956Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 3}],"ok" : 1,"operationTime" : Timestamp(1697179502, 1),"$clusterTime" : {"clusterTime" : Timestamp(1697179502, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
1.5 副本集读写操作
接下来我们测试三个不同角色的节点的数据读写情况。登录主节点 27017,写入和读取数据
myrs:PRIMARY> use articledb
switched to db articledb
myrs:PRIMARY> db
articledb
myrs:PRIMARY> db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date()})
WriteResult({ "nInserted" : 1 })
myrs:PRIMARY> db.comment.find()
{ "_id" : ObjectId("6528e8155dabb447bc9211d2"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2023-10-13T06:47:49.542Z") }
登录从节点 27018
myrs:SECONDARY> show dbs
2023-10-13T00:06:41.119-0700 E QUERY [js] Error: listDatabases failed:{"operationTime" : Timestamp(1697180793, 1),"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk","$clusterTime" : {"clusterTime" : Timestamp(1697180793, 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:151:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1
发现,不能读取集合的数据。当前从节点只是一个备份,不是奴隶节点,无法读取数据,写当然更不行。
因为默认情况下,从节点是没有读写权限的,可以增加读的权限,但需要进行设置。
# 设置读操作权限
# 该命令是 db.getMongo().setSlaveOk() 的简化命令。
rs.slaveOk() 或 rs.slaveOk(true)
# 在 27018 上设置作为奴隶节点权限,具备读权限
myrs:SECONDARY> rs.slaveOk()
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
# 执行查询命令,运行成功!
myrs:SECONDARY> show dbs
admin 0.000GB
articledb 0.000GB
config 0.000GB
local 0.000GB
myrs:SECONDARY> db.comment.find()
myrs:SECONDARY> use articledb
switched to db articledb
myrs:SECONDARY> db.comment.find()
{ "_id" : ObjectId("6528e8155dabb447bc9211d2"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2023-10-13T06:47:49.542Z") }
# 但仍然不允许插入
myrs:SECONDARY> db.comment.insert({"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,k一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"})
WriteCommandError({"operationTime" : Timestamp(1697181093, 1),"ok" : 0,"errmsg" : "not master","code" : 10107,"codeName" : "NotMaster","$clusterTime" : {"clusterTime" : Timestamp(1697181093, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
})
现在实现了读写分离,让主插入数据,让从来读取数据。
如果要取消作为奴隶节点的读权限:
rs.slaveOk(false)
# 在 27018 取消设置奴隶节点权限
myrs:SECONDARY> rs.slaveOk(false)
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
# 无法再查看数据
myrs:SECONDARY> db.comment.find()
Error: error: {"operationTime" : Timestamp(1697181203, 1),"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk","$clusterTime" : {"clusterTime" : Timestamp(1697181203, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
}
仲裁者节点,不存放任何业务数据的,可以登录查看
# 登录 27019 节点
/usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27019# 设置为奴隶节点
myrs:ARBITER> rs.slaveOk()
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
# 无法查看相关信息
myrs:ARBITER> show dbs
2023-10-13T00:15:19.072-0700 E QUERY [js] Error: listDatabases failed:{"ok" : 0,"errmsg" : "node is not in primary or recovering state","code" : 13436,"codeName" : "NotMasterOrSecondary"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:151:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1
1.6 主节点的选举原则
MongoDB 在副本集中,会自动进行主节点的选举,主节点选举的触发条件:
a、主节点故障
b、主节点网络不可达(默认心跳信息为10秒)
c、人工干预(rs.stepDown(600))
一旦触发选举,就要根据一定规则来选主节点。选举规则是根据票数来决定谁获胜:
票数最高,并且获得了 “大多数” 成员的投票支持的节点获胜。
“大多数” 的定义为:假设复制集内投票成员数量为 N,则大多数为 N/2 + 1。例如:3 个投票成员,则大多数的值是 2。当复制集内存活成员数量不足大多数时,整个复制集将无法选举出 Primary,复制集将无法提供写服务,处于只读状态。
若票数相同,且都获得了“大多数”成员的投票支持的,数据新的节点获胜。
数据的新旧是通过操作日志 oplog 来对比的。
在获得票数的时候,优先级(priority)参数影响重大。
可以通过设置优先级(priority)来设置额外票数。优先级即权重,取值为 0-1000,相当于可额外增加 0-1000 的票数,优先级的值越大,就越可能获得多数成员的投票(votes)数。指定较高的值可使成员更有资格成为主要成员,更低的值可使成员更不符合条件。
默认情况下,优先级的值是 1
myrs:PRIMARY> rs.conf()
{"_id" : "myrs","version" : 3,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,"members" : [{"_id" : 0,"host" : "192.168.229.154:27017","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 1,"host" : "192.168.229.154:27018","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 2,"host" : "192.168.229.154:27019","arbiterOnly" : true,"buildIndexes" : true,"hidden" : false,"priority" : 0,"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("6528b761af0089c47768dd07")}
}
可以看出,主节点和副本节点的优先级各为 1,即,默认可以认为都已经有了一票。但选举节点,优先级是 0,(要注意是,官方说了,选举节点的优先级必须是 0,不能是别的值。即不具备选举权,但具有投票权)。
1.7 故障测试
1.7.1 副本节点故障测试
首先关闭 27018 副本节点。主节点和仲裁节点对 27018 的心跳失败。但是因为主节点还在,因此,没有触发投票选举。如果此时,在主节点写入数据。
db.comment.insert({"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"})
再次启动 27018 从节点,会发现,主节点写入的数据,会自动同步给从节点。
1.7.2 主节点故障测试
关闭 27017 节点,从节点和仲裁节点对 27017 的心跳失败,当失败超过 10 秒,此时因为没有主节点了,会自动发起投票。
而副本节点只有 27018,因此,候选人只有一个就是 27018,开始投票。
27019 向 27018 投了一票,27018 本身自带一票,因此共两票,超过了 “大多数”
27019 是仲裁节点,没有选举权,27018 不向其投票,其票数是 0。
最终结果,27018 成为主节点。具备读写功能。在 27018 写入数据查看。
db.comment.insert({"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"})
再启动 27017 节点,发现 27017 变成了从节点,27018 仍保持主节点。
登录 27017 节点,发现是从节点了,数据自动从 27018 同步。从而实现了高可用。
1.7.3 仲裁节点和主节点故障
先关掉仲裁节点 27019,关掉现在的主节点 27018。
登录 27017 后,发现,27017 仍然是从节点,副本集中没有主节点了,导致此时,副本集是只读状态,无法写入。
为啥不选举了?因为 27017 的票数,没有获得大多数,即没有大于等于 2,它只有默认的一票(优先级是1)如果要触发选举,随便加入一个成员即可。
如果只加入 27019 仲裁节点成员,则主节点一定是 27017,因为没得选了,仲裁节点不参与选举,但参与投票。
如果只加入 27018 节点,会发起选举。因为 27017 和 27018 都是两票,则按照谁数据新,谁当主节点。
1.7.4 仲裁节点和从节点故障
先关掉仲裁节点 27019,关掉现在的副本节点 27018,
10 秒后,27017 主节点自动降级为副本节点。(服务降级)副本集不可写数据了,已经故障了。
1.8 Compass 连接副本集
1.9 SpringDataMongoDB 连接副本集
副本集语法如下:
# slaveOk=true :开启副本节点读的功能,可实现读写分离
# connect=replicaSet:自动到副本集中选择读写的主机,如果 slaveOk 是打开的,则实现了读写分离
mongodb://host1,host2,host3/数据库名称?connect=replicaSet&laveOk=true$replicaSet=副本集名字
修改我们自己的 application.yml 文件,如下所示:
spring:# 数据源配置data:mongodb:# 主机地址# host: 192.168.229.154# 数据库# database: articledb# 默认端口是27017# port: 27017# 也可以使用uri连接uri: mongodb://192.168.229.154:27017,192.168.229.154:27018,192.168.229.154:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
注意:
SpringDataMongoDB 自动实现了读写分离。
写操作时,只打开主节点连接;
读操作时,同时打开主节点和从节点连接,但使用从节点获取数据。
相关文章:

MongoDB 集群配置
一、副本集 Replica Sets 1.1 简介 MongoDB 中的副本集(Replica Set)是一组维护相同数据集的 mongod 服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。 也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就…...

random生成随机数的灵活运用
random返回的 [0,1) 之间的一个随即小数 思考:请写出获取 a-b 之间的一个随机整数,a,b均为整数,比如 a2 , b7 即返回一个数 x > [2,7]Math.random()*(b-a) 返回的就是 [0,b-a](int)(aMath.random()*(b-a1)) 》 (int)(2Math.random()*6) Ma…...

宏定义实现二进制数的奇偶位交换
思路分析 通过宏定义来实现二进制数的奇偶位交换,如果一个个遍历交换的话,那得算到猴年马月,这是我在网上看到的一个思路: 我们将每一位(整数在计算机里存储是4字节,32位)二进制数的奇数位保留…...

【ELK 使用指南】ELK + Filebeat 分布式日志管理平台部署
ELK和EFLK 一、前言1.1 日志分析的作用1.2 需要收集的日志1.3 完整日志系统的基本特征 二、ELK概述2.1 ELK简介2.2 为什么要用ELK?2.3 ELK的组件 三、ELK组件详解3.1 Logstash3.1.1 简介3.1.2 Logstash命令常用选项3.1.3 Logstash 的输入和输出流3.1.4 Logstash配置文件 3.2 E…...

传输层 | UDP协议、TCP协议
之前讲过的http与https都是应用层协议,当应用层协议将报文构建好之后就要将报文往下层传输层进行传递,而传输层就是负责将数据能够从发送端传到接收端。 再谈端口号 端口号(port)标识了一个主机上进行通信的不同的应用程序,在TCP/IP协议中&…...

Webmin(CVE-2019-15107)远程命令执行漏洞复现
漏洞编号 CVE-2019-15107 webmin介绍 什么是webmin Webmin是目前功能最强大的基于Web的Unix系统管理工具。管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作http://www.webmin.com/Webmin 是一个用 Perl 编写的基于浏览器的管理应用程序。是一个基于Web的界面…...

嵌入式实时操作系统的设计与开发 (前后台系统)
前后台结构 前后台系统也称为中断驱动系统,其软件结构的显著特点是运行的程序有前台和后台之分。 在后台,一组程序按照轮询方式访问CPU;在前台,当用户的请求到达时,首先向CPU触发中断,然后将该请求转交给后…...

Macos数字音乐库:Elsten Software Bliss for Mac
Elsten Software Bliss for Mac是一款优秀的音乐管理软件,它可以帮助用户自动化整理和标记数字音乐库,同时可以自动识别音乐信息并添加标签和元数据。 此外,Bliss还可以修复音乐库中的问题,例如重复的音乐文件和缺失的专辑封面等…...

基于SpringBoot的校园周边美食探索及分享平台的设计与实现
文章目录 项目介绍主要功能截图:登录注册个人信息管理后台首页轮播图管理美食鉴赏我的好友管理我的收藏管理用户管理部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给…...

GPT-4V的图片识别和分析能力
GPT-4V是OpenAI开发的大型语言模型,是GPT-4的升级版本。GPT-4V在以下几个方面进行了改进: 模型规模更大:GPT-4V的参数量达到了1.37T,是GPT-4的10倍。训练数据更丰富:GPT-4V的训练数据包括了1.56T的文本和代码数据。算…...

蓝桥杯(等差素数列,C++)
思路: 1、因为找的是长度为10,且公差最小的等差素数列,直接用枚举即可。 2、枚举用三重循环,第一重枚举首项,第二重枚举公差,第三重因为首项算一个,所以枚举九个等差素数。 代码:…...

Ceph 中的写入放大
新钛云服已累计为您分享769篇技术干货 介绍 Ceph 是一个开源的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。 Ceph 独一无二地在一个统一的系统中同时提供了对象、块、和文件存储功能。 Ceph 消除了对系统单一中心节点的依赖,实现了无中…...

Mabatis-puls强于Mybatis的地方
Mabatis-puls与Mybatis都是优秀的Java持久化框架,但是Mabatis-puls相较于Mybatis有以下几个方面的优势: 性能更优:Mabatis-puls采用了Javassist技术,使得它在运行时比Mybatis更快速,尤其是在执行大量SQL的情况下&#…...

vue项目npm intall时发生版本冲突的解决办法
在日常使用命令npm install / npm install XX下载依赖的操作中,我经常会遇到无法解析依赖树的问题(依赖冲突) 当遇到这种情况的时候,可以通过以下命令完成依赖安装: npm install --legacy-peer-deps npm install xxx…...

tomcat多实例部署jenkins
tomcat多实例部署jenkins 文章目录 tomcat多实例部署jenkins1.简介:2.优缺点:3.工作原理:4.工作流程:5.tomcat多实例部署jenkins流程5.1.环境说明5.2.部署前准备工作5.3.多实例部署tomcat5.4.部署jenkins5.5.创建一个jenkins项目5…...

强连通分量+缩点
[图论与代数结构 701] 强连通分量 题目描述 给定一张 n n n 个点 m m m 条边的有向图,求出其所有的强连通分量。 注意,本题可能存在重边和自环。 输入格式 第一行两个正整数 n n n , m m m ,表示图的点数和边数。 接下来…...

如何做系统架构设计
文章目录 1、如何进行架构设计体系架构需求体系架构设计体系架构文档化体系架构复审体系架构实现体系架构演化 2、架构设计注意事项分治原则服务自治拥抱变化可维护性考虑依赖和限制阅读代码注意事项 3、最后 系统架构应该如何设计,从自己做架构的经历来分享一些体…...

L14D6内核模块编译方法
一、内核模块基础代码解析 一个内核模块代码错误仍然会导致的内核崩溃。 GPL协议:开源规定,使用内核一些函数需要 1、单内核的缺点 单内核扩展性差的缺点减小内核镜像文件体积,一定程度上节省内存资源提高开发效率不能彻底解决稳定性低的缺…...

PyTorch入门教学——dir()函数和help()函数的应用
1、简介 已知PyTorch是一个工具包,其中包含许多功能函数。dir()函数和help()函数是学习PyTorch包的重要法宝。 dir():能让我们知道工具包以及工具包中的分隔区有什么东西。help():能让我们知道每个工具是如何使用的,即工具的使用…...

使用Elasticsearch来进行简单的DDL搜索数据
说明:Elasticsearch提供了多种多样的搜索方式来满足不同使用场景的需求,我们可以使用Elasticsearch来进行各种复制的查询,进行数据的检索。 1.1 精准查询 用来查询索引中某个类型为keyword的文本字段,类似于SQL的“”查询。 创…...

【软考】9.3 二叉树存储/遍历/线索/最优/查找/平衡
《树与二叉树》 二叉树的顺序存储结构 顺序存储只适用于完全二叉树和满二叉树,一般二叉树不适用i 2 的左孩子为 2i 4,右孩子为 2i 1 5 二叉树的链式存储结构 链式存储适用于二叉树;空结点用“∧”表示二叉链表:左孩子࿰…...

关于矿井地面电力综合自动化系统的研究与产品选型
安科瑞 崔丽洁 摘要:煤矿供电系统是煤矿生产的重要动力保障 , 一旦电力中断 , 生产将被迫停止 , 同时停电后容易发生瓦斯积聚爆炸、淹井等恶性事故,现有配电室采用不同厂商的保护装 置产品,没有形成有效的监控配电系统,不便于管…...

论文阅读:Offboard 3D Object Detection from Point Cloud Sequences
目录 概要 Motivation 整体架构流程 技术细节 3D Auto Labeling Pipeline The static object auto labeling model The dynamic object auto labeling model 小结 论文地址:[2103.05073] Offboard 3D Object Detection from Point Cloud Sequences (arxiv.o…...

Python学习基础笔记六十八——循环
循环是编程语言常见的流程控制。 Python语句要让计算机反复地做一些事情,就要用到循环语句。 有While和for循环。 while循环: command input("请输入命令:") while command ! exit:print(f输入的命令是{command})command input("请输…...

部署k8s dashboard(这里使用Kubepi)
9. 部署k8s dashboard(这里使用Kubepi) Kubepi是一个简单高效的k8s集群图形化管理工具,方便日常管理K8S集群,高效快速的查询日志定位问题的工具 部署KubePI(随便在哪个节点部署,我这里在主节点部署&#…...

Java Lambda表达式的使用
我们了解了 java Lambda 的概念并可以在匿名类的场合使用 Lambda 语法进行简单替换。本节主要介绍在 Java 中如何使用 Lambda 表达式。 作为参数使用Lambda表达式 Lambda 表达式一种常见的用途就是作为参数传递给方法,这需要声明参数的类型声明为函数式接口类型。…...

【初始C语言8】详细讲解初阶结构体的知识
前言 💓作者简介: 加油,旭杏,目前大二,正在学习C,数据结构等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏…...

<C++> IO流
C语言的输入与输出 在C语言当中,我们使用最频繁的输入输出方式就是scanf与printf: scanf: 从标准输入设备(键盘)读取数据,并将读取到的值存放到某一指定变量当中。printf: 将指定的数据输出到…...

基于单目相机的2D测量(工件尺寸和物体尺寸)
目录 1.简介 2.基于单目相机的2D测量 2.1 想法: 2.2 代码思路 2.2 主函数部分 1.简介 基于单目相机的2D测量技术在许多领域中具有重要的背景和意义。 工业制造:在工业制造过程中,精确测量是确保产品质量和一致性的关键。基于单目相机的2…...

23面向对象案例1
目录 1、计算连续表达式的一个过程 2、优化后的代码 为什么不能return resultn? 3、用面向对象的方法可以解决冗余的问题,但是还是不能解决result的值可以被随意修改的问题 4、解决不能被随意修改的问题,可以将类属性改成私有变量吗&…...