1、副本集部署教程
1.1、要求
三个成员副本集提供足够的冗余以承受大多数网络分区和其他系统故障。这些副本集也具有足够的容量用于许多分布式读取操作。副本集应始终具有奇数个成员。这可确保选举顺利进行。对于生产部署,应该通过在不同的计算机上托管mongod实例来尽可能多地保持成员之间的分离。当使用虚拟机进行生产部署时,应将每个mongod实例放在由冗余电源电路和冗余网络路径服务的单独host服务器上。
1.2、注意事项
- 架构体系:在生产环境,将副本集的每个成员部署到自己的机器上,并尽可能绑定到mongod的标准端口27017上。
- 主机名称:如果可能,在部署副本集或分配集群时,使用逻辑域名代替ip地址。使用域名代替ip可以防止ip改变时配置的更改。
- ip绑定:使用bind_ip选项来保证mongod监听来自指定ip的应用的连接。默认情况下,绑定的是本地localhost,此时mongod只接受本地的mongo的shell、副本集或分片集群的其他成员的连接。若需要绑定其他ip地址,可以使用net.bindIp配置或使用bind_ip命令行来指定主机名或ip地址列表。
1.3、副本集部署
1.3.1、数据目录创建
创建如下三个目录:用于保存mongod数据及日志等。
"C:\mongo\data27017"
"C:\mongo\data27018"
"C:\mongo\data27019"
1.3.1、启动mongod实例
./mongod.exe --replSet mongoset --dbpath "C:\mongo\data27017" --port 27017 --logpath "C:\mongo\data27017\log.log"
./mongod.exe --replSet mongoset --dbpath "C:\mongo\data27018" --port 27018 --logpath "C:\mongo\data27018\log.log"
./mongod.exe --replSet mongoset --dbpath "C:\mongo\data27019" --port 27019 --logpath "C:\mongo\data27019\log.log"
1.3.2、初始副本集
mongoset:PRIMARY> rsconf = {
... _id: "mongoset",
... members: [{
... _id: 0,
... host: "localhost:27017"
... }, {
... _id: 1,
... host: "localhost:27018"
... }, {
... _id: 2,
... host: "localhost:27019"
... }]
... }
{
"_id" : "mongoset",
"members" : [
{
"_id" : 0,
"host" : "localhost:27017"
},
{
"_id" : 1,
"host" : "localhost:27018"
},
{
"_id" : 2,
"host" : "localhost:27019"
}
]
}
mongoset:PRIMARY> rs.initiate(rsconf)
{
"operationTime" : Timestamp(1577706032, 1),
"ok" : 0,
"errmsg" : "already initialized",
"code" : 23,
"codeName" : "AlreadyInitialized",
"$clusterTime" : {
"clusterTime" : Timestamp(1577706032, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
mongoset:PRIMARY>
1.3.3、查看副本集状态
mongoset:PRIMARY> rs.conf()
{
"_id" : "mongoset",
"version" : 29603,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "localhost:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "localhost:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "localhost:27019",
"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("5e01feb0815cdc9cd73d4fca")
}
}
mongoset:PRIMARY>
mongoset:PRIMARY> rs.status()
{
"set" : "mongoset",
"date" : ISODate("2019-12-30T11:43:31.227Z"),
"myState" : 1,
"term" : NumberLong(14),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"lastCommittedWallTime" : ISODate("2019-12-30T11:43:22.516Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"readConcernMajorityWallTime" : ISODate("2019-12-30T11:43:22.516Z"),
"appliedOpTime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"durableOpTime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"lastAppliedWallTime" : ISODate("2019-12-30T11:43:22.516Z"),
"lastDurableWallTime" : ISODate("2019-12-30T11:43:22.516Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1577706172, 1),
"lastStableCheckpointTimestamp" : Timestamp(1577706172, 1),
"members" : [
{
"_id" : 0,
"name" : "localhost:27017",
"ip" : "127.0.0.1",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 519,
"optime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"optimeDate" : ISODate("2019-12-30T11:43:22Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1577705751, 1),
"electionDate" : ISODate("2019-12-30T11:35:51Z"),
"configVersion" : 29603,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "localhost:27018",
"ip" : "127.0.0.1",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 463,
"optime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"optimeDurable" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"optimeDate" : ISODate("2019-12-30T11:43:22Z"),
"optimeDurableDate" : ISODate("2019-12-30T11:43:22Z"),
"lastHeartbeat" : ISODate("2019-12-30T11:43:31.127Z"),
"lastHeartbeatRecv" : ISODate("2019-12-30T11:43:29.872Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "localhost:27017",
"syncSourceHost" : "localhost:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 29603
},
{
"_id" : 2,
"name" : "localhost:27019",
"ip" : "127.0.0.1",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 446,
"optime" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"optimeDurable" : {
"ts" : Timestamp(1577706202, 1),
"t" : NumberLong(14)
},
"optimeDate" : ISODate("2019-12-30T11:43:22Z"),
"optimeDurableDate" : ISODate("2019-12-30T11:43:22Z"),
"lastHeartbeat" : ISODate("2019-12-30T11:43:31.127Z"),
"lastHeartbeatRecv" : ISODate("2019-12-30T11:43:30.220Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "localhost:27018",
"syncSourceHost" : "localhost:27018",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 29603
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1577706202, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1577706202, 1)
}
mongoset:PRIMARY>
2、副本集配置
2.1、调整节点优先级
副本集成员的priority设置会影响主要的选举的时间和结果。高优先级成员更有可能召集选举,更有可能获胜。使用此设置可确保某些成员更有可能成为主要成员,而其他成员永远不会成为主要成员。成员的优先级priority的 value 决定了选举中成员的优先。数字越大,优先级越高。
priority的值可以是0-1000之间的任何浮点数,其默认值为1。若有阻止成员选举为主节点,可将其优先级设置为0。隐藏及延迟成员将优先级设置0。非选举节点优先级必须为0,仲裁者优先级为0。
在计划的维护窗口更改优先级配置,将导致主节点强制断开所有连接,重新开始选举。
2.2、设置隐藏节点
如果settings.chainingAllowed设置允许辅助成员从其他辅助节点同步,则默认情况下 MongoDB 在选择同步目标时更喜欢隐藏成员上的 non-hidden 成员。 MongoDB 只会选择隐藏的成员作为最后的手段。如果希望辅助节点从隐藏成员同步,请使用replSetSyncFrom database 命令覆盖默认同步目标。
隐藏成员配置示例:
{
"_id" :
"host" : ,
"priority" : 0,
"hidden" : true
}
cfg = rs.conf()
cfg.members[0].priority = 0
cfg.members[0].hidden = true
rs.reconfig(cfg)
在 re-configuring 副本集之后,此辅助成员的优先级为0,因此它不能成为主要成员并被隐藏。集合中的其他成员不会在isMaster或db.isMaster()输出中公布隐藏成员。rs.reconfig() shell 方法可以强制当前主节点降级,这会导致重新选举。
2.3、设置延迟节点
要配置延迟的辅助成员,请将其成员priority的value设置为0,将其成员hidden的value 设置为true,将其成员slaveDelay的value 设置为延迟的秒数。配置延迟成员时,延迟同时适用于复制和成员的OPLOG。
示例:
cfg = rs.conf()
cfg.members[0].priority = 0
cfg.members[0].hidden = true
cfg.members[0].slaveDelay = 3600
rs.reconfig(cfg)
2.4、配置非选举节点
Non-voting 成员允许在最多七个投票成员之外添加其他成员以进行读分发,Non-voting 成员的投票值及优先级都必须为0。
示例:
cfg.members[3].votes = 0;
cfg.members[3].priority = 0;
cfg.members[4].votes = 0
cfg.members[4].priority = 0;
cfg.members[5].votes = 0
cfg.members[5].priority = 0;
2.5、将辅助节点转换为仲裁者
将辅助节点转换为仲裁者步骤如下:
- 使用rs.remove()删除副节点,并使用rs.conf()或rs.status()验证是否删除;
- 将副节点的数据进行备份,并删除原有数据;
- 重新启动此副节点;
- 使用rs.addArb()命令将此节点以仲裁者添加到副本集中;
- 使用rs.conf()或rs.status()进行验证;
2.6、更改oplog大小
可使用replSetResizeOplog命令更改副本集的每个成员上的 oplog 大小。首先在每个副节点上执行这些步骤,更改所有辅助成员的 oplog 大小,然后再在主节点上执行更改。
- 先使用mongo的shell连接上节点;
- 使用一下命令查看oplog大小。
use local
db.oplog.rs.stats().maxSize
- 使用replSetResizeOplog命令更改oplog大小;
db.adminCommand({replSetResizeOplog: 1, size: 16000})
- 压缩oplog.rs空间:减小 oplog 的大小不会自动回收分配给原始 oplog 大小的磁盘空间。需要进行手动回收。
use local
db.runCommand({ "compact" : "oplog.rs" } )
2.7、强迫某个节点成为主节点
将某个节点的优先级设置为比其他节点更大的值,则此节点比其他节点更可能成为主节点。
2.8、管理链式复制
MongoDB 支持链式复制。当次要成员从另一个辅助成员而不是从主复制时,会发生链式复制。链式复制可以减少主要负载。但链式复制还可能导致复制延迟增加,具体取决于网络的拓扑结构。在链式复制导致滞后的情况下,可以使用副本集 Configuration中的settings.chainingAllowed设置禁用链式复制,MongoDB 默认启用链式复制。
使能链式复制:
cfg = rs.config()
cfg.settings.chainingAllowed = true
rs.reconfig(cfg)
2.9、更改主机名
对于大多数副本 sets,成员[n] .host字段中的主机名永远不会改变。但是,如果组织需求发生更改,则可能需要迁移部分或全部 host 名称。
use local
cfg = db.system.replset.findOne( { "_id": "rs" } )
cfg.members[0].host = "mongodb0.example.net:27017"
cfg.members[1].host = "mongodb1.example.net:27017"
cfg.members[2].host = "mongodb2.example.net:27017"
db.system.replset.update( { "_id": "rs" } , cfg )
3、副本集配置详解
副本集配置如下:
{
_id: ,
version: ,
protocolVersion: ,
writeConcernMajorityJournalDefault: ,
configsvr: ,
members: [
{
_id: ,
host: ,
arbiterOnly: ,
buildIndexes: ,
hidden: ,
priority: ,
tags: ,
slaveDelay: ,
votes:
},
...
],
settings: {
chainingAllowed : ,
heartbeatIntervalMillis : ,
heartbeatTimeoutSecs: ,
electionTimeoutMillis : ,
catchUpTimeoutMillis : ,
getLastErrorModes : ,
getLastErrorDefaults : ,
replicaSetId:
}
}
3.1、_id:string
副本集名称,设置后无法更改。_id必须与命令 line 上为mongod指定的-replSet 的replication.replSetName或 value 相同。
3.2、version:int
用于区分副本集configuration 的修订版与 configuration 的先前迭代的递增编号。
3.3、configsvr:boolean
默认值false,指示副本集是否用于分片 cluster 的配置服务器。如果副本集用于分片 cluster 的配置服务器,则设置为true。
3.4、protocolVersion:int
默认值1,表示新副本集的协议版本。
3.5、writeConcernMajorityJournalDefault:Boolean
默认值:如果protocolVersion为 1,则为 true;如果protocolVersion为 0,则为 false。如果写入关注点未明确指定日志选项Ĵ,则确定\ {w:“多数”}写入问题的行为。
值 | { w: "majority" }行为 |
---|---|
true | MongoDB 在大多数投票成员写入 on-disk 期刊后确认写操作。 重要事项,当writeConcernMajorityJournalDefault为true时,副本集的所有投票成员必须运行日记功能。 如果副本集的任何投票成员在没有日记且writeConcernMajorityJournalDefault的情况下运行true,“多数”写入操作可能会失败。这些包括固有地使用“多数”写入关注的操作,例如replSetStepDown命令,或者默认使用“多数”写入关注的各种mongo shell 方法,例如用户管理方法和角色管理方法。 从 version 3.6.14 开始,如果副本集成员使用in-memory 存储引擎(投票或 non-voting)但副本集的writeConcernMajorityJournalDefault设置为 true,则副本集成员会记录启动警告。 |
false | MongoDB 在大多数投票成员在 memory 中应用了该操作后,确认了写操作。 警告 ,如果副本集的任何投票成员在没有日记的情况下运行(i.e.要么运行 in-memory 存储引擎,要么在禁用日记功能的情况下运行),则必须将 writeConcernMajorityJournalDefault 设置为 false。 警告,如果副本集的任何投票成员在没有日记(i.e.运行in-memory 存储引擎或运行且禁用日记功能)的情况下运行,则必须将writeConcernMajorityJournalDefault设置为false。 从 version 3.6.14 开始,如果副本集成员使用in-memory 存储引擎(投票或 non-voting)但副本集的writeConcernMajorityJournalDefault设置为 true,则副本集成员会记录启动警告。 |
3.6、members:array
成员 configuration 文档的 array,一个用于副本集的每个成员。 会员 array 是 zero-indexed array。
每个 member-specific configuration 文档都可以包含以下字段:
- members[n]. _id:int类型,副本集中每个成员的 integer 标识符。值必须介于 0 和 255 之间(包括 0 和 255)。每个副本集成员必须具有唯一的_id。设置后,您无法更改成员的_id。
- members[n]. host:string类型,设置成员的主机名和(如果指定)port 编号。主机名 name 必须可以为副本集中的每个 host 解析。
- members[n]. arbiterOnly:boolean类型,标识是否为仲裁者,使用rs.addArb()方法添加仲裁器时,该方法会自动为添加的成员设置arbiterOnly为true。
- members[n]. buildIndexes:boolean类型,指示mongod是否在此成员上构建索引。将成员添加到集合后,您无法更改成员[n] .buildIndexes字段。
- members[n]. hidden:boolean类型,默认false,当此 value 为true时,副本集会隐藏此实例,并且不会在db.isMaster()或isMaster的输出中包含该成员。这可以防止读操作通过读偏好到达此 host。隐藏成员可以确认使用写关注发出的写操作。对于以“多数”写入问题发出的写操作,该成员也必须是一个投票成员(投票值大于0)。
- members[n]. priority:类型double,0-1000的浮点型数字,默认值为1。指定节点优先级,优先级较高的更可能成为主节点。
- members[n]. tags:map对象,默认值none。节点标签字段。可以在读偏好或写关注中指定标记集。
- members[n]. slaveDelay:int,默认值0。此副本集成员滞后主节点的秒数。拥有创建延迟节点。
- members[n]. votes:int,默认值1。节点投票票数,每个成员拥有的投票数为1或0,仲裁者总是具有1投票权,优先大于 0 的成员不能有 0 票。副本集最多可以有50 成员但只有 7 个投票成员。如果在一个副本集中需要超过 7 个成员,请将成员[n] .votes设置为0以用于其他 non-voting 成员。
3.7、settings:副本集配置
配置包含以下选项:
- settings. chainingAllowed:boolean,默认值true。当settings.chainingAllowed是true时,副本集允许次要成员从其他辅助成员复制。当settings.chainingAllowed是false时,辅助节点只能从主复制。
- settings. getLastErrorDefaults:文档。指定副本集的写关注配置。仅当写操作或GetLastError 函数未指定其他写入问题时,副本集才会使用此写入问题。如果未设置settings.getLastErrorDefaults,则副本集的默认写入问题仅需要来自主服务器的确认。
- settings. getLastErrorModes:文档。用于通过使用成员[n] .tags定义自定义写关注的文档。自定义写入问题可以提供data-center 意识。
- settings. heartbeatTimeoutSecs:int,默认值10。副本集成员等待彼此成功心跳的秒数。如果成员未在 time 中回复,则其他成员会将逾期成员标记为无法访问。
- settings. electionTimeoutMillis:int,默认值10000(ms)。用于检测副本集的主节点何时无法访问的 time 限制(以毫秒为单位)。值越高,故障转移越慢,但对主节点或网络缓慢或紊乱的敏感性降低。较低的值会导致更快的故障转移,但会增加对主节点或网络缓慢或污染的敏感度。
- settings. catchUpTimeoutMillis:int,默认值-1(无限)。新选择的主节点与可能具有更近期写入的其他副本集成员同步(赶上)的时间限制(以毫秒为单位)。无限或高 time 限制可能会减少其他成员在选举后需要回滚的数据量,但可能会增加故障转移 time。
- settings. catchUpTakeoverDelayMillis:int,默认值30000(ms)。在确定它超出当前主之后,节点等待启动捕获接管的时间(以毫秒为单位)。在捕获接管期间,当前主节点之前的节点启动选举以成为副本集的新主节点。
- settings. heartbeatIntervalMillis:类型int,节点接心跳间隔(ms)。
- settings. replicaSetId:类型ObjectId。与副本集关联的 ObjectId,在rs.initiate()或replSetInitate期间自动创建。你无法改变replicaSetId。
4、副本集命令详解
4.1、副本集的shell命令:
| 名称 | 描述 |
| rs.add() | 将成员添加到副本集。 |
| rs.addArb() | 将仲裁者添加到副本集。 |
| rs.conf() | 返回副本集 configuration 文档。 |
| rs.freeze() | 阻止当前成员在 time 期间寻求选举。 |
| rs.help() | 返回副本集函数的基本帮助文本。 |
| rs.initiate() | 初始化新的副本集。 |
| rs.printReplicationInfo() | 从主数据库的角度打印副本集状态的报告。 |
| rs.printSlaveReplicationInfo() | 从辅助节点的角度打印副本集状态的报告。 |
| rs.reconfig() | Re-configures 通过应用新副本集 configuration object 设置副本。 |
| rs.remove() | 从副本集中删除成员。 |
| rs.slaveOk() | 为当前连接设置slaveOk property。已过时。使用readPref()和Mongo.setReadPref()设置阅读偏好。 |
| rs.status() | 返回包含有关副本集的 state 的信息的文档。 |
| rs.stepDown() | 导致当前主成为强制选举的辅助。 |
| rs.syncFrom() | 设置此副本集成员将同步的成员,覆盖默认同步目标选择逻辑。 |
4.2、副本集的数据命令:
名称 | 描述 |
---|---|
applyOps | 将OPLOG条目应用于当前数据集的内部命令。 |
isMaster | 显示有关此成员在副本集中的角色的信息,包括它是否为 master。 |
replSetAbortPrimaryCatchUp | 强制选举的主中止同步(赶上)然后完成向主要的过渡。 |
replSetFreeze | 阻止当前成员在 time 期间选举主。 |
replSetGetConfig | 返回副本集的 configuration object。 |
replSetGetStatus | 返回报告副本集状态的文档。 |
replSetInitiate | 初始化新的副本集。 |
replSetMaintenance | 启用或禁用维护模式,该模式将次要节点放在RECOVERING state 中。 |
replSetReconfig | 将新的 configuration 应用于现有副本集。 |
replSetResizeOplog | 动态调整副本集成员的 oplog 大小。仅适用于 WiredTiger 存储引擎。 |
replSetStepDown | 强制当前主到 step 下降并成为次要,迫使选举。 |
replSetSyncFrom | 显式覆盖用于选择要复制的成员的默认逻辑。 |
重新同步 | 从主强制mongod到 re-synchronize。仅适用于 master-slave 复制。 |