MongoDB 副本集的常用操作及原理

本文是对MongoDB副本集常用操作的一个汇总,同时也穿插着介绍了操作背后的原理及注意点。

结合之前的文章:MongoDB副本集的搭建,大家可以在较短的时间内熟悉MongoDB的搭建和管理。

下面的操作主要分为两个部分:

1. 修改节点状态

主要包括:

1> 将Primary节点降级为Secondary节点

2> 冻结Secondary节点

3> 强制Secondary节点进入维护模式

2. 修改副本集的配置

1> 添加节点

2> 删除节点

3> 将Secondary节点设置为延迟备份节点

4> 将Secondary节点设置为隐藏节点

5> 替换当前的副本集成员

6> 设置副本集节点的优先级

7> 阻止Secondary节点升级为Primary节点

8> 如何设置没有投票权的Secondary节点

9> 禁用chainingAllowed

10> 为Secondary节点显式指定复制源

11> 禁止Secondary节点创建索引

首先查看MongoDB副本集支持的所有操作

> rs.help()
    rs.status()                                { replSetGetStatus : 1 } checks repl set status
    rs.initiate()                              { replSetInitiate : null } initiates set with default settings
    rs.initiate(cfg)                           { replSetInitiate : cfg } initiates set with configuration cfg
    rs.conf()                                  get the current configuration object from local.system.replset
    rs.reconfig(cfg)                           updates the configuration of a running replica set with cfg (disconnects)
    rs.add(hostportstr)                        add a new member to the set with default attributes (disconnects)
    rs.add(membercfgobj)                       add a new member to the set with extra attributes (disconnects)
    rs.addArb(hostportstr)                     add a new member which is arbiterOnly:true (disconnects)
    rs.stepDown([stepdownSecs, catchUpSecs])   step down as primary (disconnects)
    rs.syncFrom(hostportstr)                   make a secondary sync from the given member
    rs.freeze(secs)                            make a node ineligible to become primary for the time specified
    rs.remove(hostportstr)                     remove a host from the replica set (disconnects)
    rs.slaveOk()                               allow queries on secondary nodes

    rs.printReplicationInfo()                  check oplog size and time range
    rs.printSlaveReplicationInfo()             check replica set members and replication lag
    db.isMaster()                              check who is primary

    reconfiguration helpers disconnect from the database so the shell will display
    an error, even if the command succeeds.

修改节点状态

将Primary节点降级为Secondary节点

myapp:PRIMARY> rs.stepDown()

这个命令会让primary降级为Secondary节点,并维持60s,如果这段时间内没有新的primary被选举出来,这个节点可以要求重新进行选举。

也可手动指定时间

myapp:PRIMARY> rs.stepDown(30)

在执行完该命令后,原Secondary node3:27017升级为Primary。

其日志输出为:

2017-05-03T22:24:21.009+0800 I COMMAND  [conn8] Attempting to step down in response to replSetStepDown command
2017-05-03T22:24:25.967+0800 I -        [conn8] end connection 127.0.0.1:45976 (3 connections now open)
2017-05-03T22:24:37.643+0800 I REPL     [ReplicationExecutor] Member node3:27018 is now in state SECONDARY
2017-05-03T22:24:41.123+0800 I REPL     [replication-40] Restarting oplog query due to error: InterruptedDueToReplStateChange: operat
ion was interrupted. Last fetched optime (with hash): { ts: Timestamp 1493821475000|1, t: 2 }[-6379771952742605801]. Restarts remaining: 32017-05-03T22:24:41.167+0800 I REPL     [replication-40] Scheduled new oplog query Fetcher source: node3:27018 database: local query:
 { find: "oplog.rs", filter: { ts: { $gte: Timestamp 1493821475000|1 } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, term: 2 } query metadata: { $replData: 1, $ssm: { $secondaryOk: true } } active: 1 timeout: 10000ms shutting down?: 0 first: 1 firstCommandScheduler: RemoteCommandRetryScheduler request: RemoteCommand 11695 -- target:node3:27018 db:local cmd:{ find: "oplog.rs", filter: { ts: { $gte: Timestamp 1493821475000|1 } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, term: 2 } active: 1 callbackHandle.valid: 1 callbackHandle.cancelled: 0 attempt: 1 retryPolicy: RetryPolicyImpl maxAttempts: 1 maxTimeMillis: -1ms2017-05-03T22:24:41.265+0800 I REPL     [replication-39] Choosing new sync source because our current sync source, node3:27018, has a
n OpTime ({ ts: Timestamp 1493821475000|1, t: 2 }) which is not ahead of ours ({ ts: Timestamp 1493821475000|1, t: 2 }), it does not have a sync source, and it‘s not the primary (sync source does not know the primary)2017-05-03T22:24:41.266+0800 I REPL     [replication-39] Canceling oplog query because we have to choose a new sync source. Current s
ource: node3:27018, OpTime { ts: Timestamp 0|0, t: -1 }, its sync source index:-12017-05-03T22:24:41.266+0800 W REPL     [rsBackgroundSync] Fetcher stopped querying remote oplog with error: InvalidSyncSource: sync
source node3:27018 (last visible optime: { ts: Timestamp 0|0, t: -1 }; config version: 1; sync source index: -1; primary index: -1) is no longer valid2017-05-03T22:24:41.266+0800 I REPL     [rsBackgroundSync] could not find member to sync from
2017-05-03T22:24:46.021+0800 I REPL     [SyncSourceFeedback] SyncSourceFeedback error sending update to node3:27018: InvalidSyncSourc
e: Sync source was cleared. Was node3:270182017-05-03T22:24:46.775+0800 I REPL     [ReplicationExecutor] Starting an election, since we‘ve seen no PRIMARY in the past 10000ms
2017-05-03T22:24:46.775+0800 I REPL     [ReplicationExecutor] conducting a dry run election to see if we could be elected
2017-05-03T22:24:46.857+0800 I REPL     [ReplicationExecutor] VoteRequester(term 2 dry run) received a yes vote from node3:27019; res
ponse message: { term: 2, voteGranted: true, reason: "", ok: 1.0 }2017-05-03T22:24:46.858+0800 I REPL     [ReplicationExecutor] dry election run succeeded, running for election
2017-05-03T22:24:46.891+0800 I REPL     [ReplicationExecutor] VoteRequester(term 3) received a yes vote from node3:27018; response me
ssage: { term: 3, voteGranted: true, reason: "", ok: 1.0 }2017-05-03T22:24:46.891+0800 I REPL     [ReplicationExecutor] election succeeded, assuming primary role in term 3
2017-05-03T22:24:46.891+0800 I REPL     [ReplicationExecutor] transition to PRIMARY
2017-05-03T22:24:46.892+0800 I ASIO     [NetworkInterfaceASIO-Replication-0] Connecting to node3:27019
2017-05-03T22:24:46.894+0800 I ASIO     [NetworkInterfaceASIO-Replication-0] Connecting to node3:27019
2017-05-03T22:24:46.894+0800 I ASIO     [NetworkInterfaceASIO-Replication-0] Successfully connected to node3:27019
2017-05-03T22:24:46.895+0800 I REPL     [ReplicationExecutor] My optime is most up-to-date, skipping catch-up and completing transiti
on to primary.2017-05-03T22:24:46.895+0800 I ASIO     [NetworkInterfaceASIO-Replication-0] Successfully connected to node3:27019
2017-05-03T22:24:47.348+0800 I REPL     [rsSync] transition to primary complete; database writes are now permitted
2017-05-03T22:24:49.231+0800 I NETWORK  [thread1] connection accepted from 192.168.244.30:35837 #9 (3 connections now open)
2017-05-03T22:24:49.236+0800 I NETWORK  [conn9] received client metadata from 192.168.244.30:35837 conn9: { driver: { name: "NetworkI
nterfaceASIO-RS", version: "3.4.2" }, os: { type: "Linux", name: "Red Hat Enterprise Linux Server release 6.7 (Santiago)", architecture: "x86_64", version: "Kernel 2.6.32-573.el6.x86_64" } }2017-05-03T22:24:49.317+0800 I NETWORK  [thread1] connection accepted from 192.168.244.30:35838 #10 (4 connections now open)
2017-05-03T22:24:49.318+0800 I NETWORK  [conn10] received client metadata from 192.168.244.30:35838 conn10: { driver: { name: "Networ
kInterfaceASIO-RS", version: "3.4.2" }, os: { type: "Linux", name: "Red Hat Enterprise Linux Server release 6.7 (Santiago)", architecture: "x86_64", version: "Kernel 2.6.32-573.el6.x86_64" } }

原Primary node3:27018降低为Secondary

2017-05-03T22:24:36.262+0800 I COMMAND  [conn7] Attempting to step down in response to replSetStepDown command
2017-05-03T22:24:36.303+0800 I REPL     [conn7] transition to SECONDARY
2017-05-03T22:24:36.315+0800 I NETWORK  [conn7] legacy transport layer closing all connections
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 5
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 4
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 4
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 3
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 1
2017-05-03T22:24:36.316+0800 I NETWORK  [conn7] Skip closing connection for connection # 1
2017-05-03T22:24:36.382+0800 I NETWORK  [thread1] connection accepted from 127.0.0.1:43359 #8 (5 connections now open)
2017-05-03T22:24:36.383+0800 I NETWORK  [conn8] received client metadata from 127.0.0.1:43359 conn8: { application: { name: "MongoDB
Shell" }, driver: { name: "MongoDB Internal Client", version: "3.4.2" }, os: { type: "Linux", name: "Red Hat Enterprise Linux Server release 6.7 (Santiago)", architecture: "x86_64", version: "Kernel 2.6.32-573.el6.x86_64" } }2017-05-03T22:24:36.408+0800 I -        [conn7] AssertionException handling request, closing client connection: 172 Operation attempt
ed on a closed transport Session.2017-05-03T22:24:36.408+0800 I -        [conn7] end connection 127.0.0.1:43355 (6 connections now open)
2017-05-03T22:24:41.262+0800 I COMMAND  [conn5] command local.oplog.rs command: find { find: "oplog.rs", filter: { ts: { $gte: Timest
amp 1493821475000|1 } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, term: 2 } planSummary: COLLSCAN cursorid:12906944372 keysExamined:0 docsExamined:1 writeConflicts:1 numYields:1 nreturned:1 reslen:392 locks:{ Global: { acquireCount: { r: 4 } }, Database: { acquireCount: { r: 2 } }, oplog: { acquireCount: { r: 2 } } } protocol:op_command 100ms2017-05-03T22:24:48.311+0800 I REPL     [ReplicationExecutor] Member node3:27017 is now in state PRIMARY
2017-05-03T22:24:49.163+0800 I REPL     [rsBackgroundSync] sync source candidate: node3:27017
2017-05-03T22:24:49.164+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Connecting to node3:27017
2017-05-03T22:24:49.236+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Successfully connected to node3:27017
2017-05-03T22:24:49.316+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Connecting to node3:27017
2017-05-03T22:24:49.318+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Successfully connected to node3:27017
2017-05-03T22:25:41.020+0800 I -        [conn4] end connection 192.168.244.30:36940 (5 connections now open)
2017-05-03T22:29:02.653+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Connecting to node3:27017
2017-05-03T22:29:02.669+0800 I ASIO     [NetworkInterfaceASIO-RS-0] Successfully connected to node3:27017
2017-05-03T22:29:41.442+0800 I -        [conn5] end connection 192.168.244.30:36941 (4 connections now open)

冻结Secondary节点

如果需要对Primary做一下维护,但是不希望在维护的这段时间内将其它Secondary节点选举为Primary节点,可以在每次Secondary节点上执行freeze命令,强制使它们始终处于Secondary节点状态。

myapp:SECONDARY> rs.freeze(100)

注:只能在Secondary节点上执行

myapp:PRIMARY> rs.freeze(100)
{
    "ok" : 0,
    "errmsg" : "cannot freeze node when primary or running for election. state: Primary",
    "code" : 95,
    "codeName" : "NotSecondary"
}

如果要解冻Secondary节点,只需执行

myapp:SECONDARY> rs.freeze()

强制Secondary节点进入维护模式

当Secondary节点进入到维护模式后,它的状态即转化为“RECOVERING”,在这个状态的节点,客户端不会发送读请求给它,同时它也不能作为复制源。

进入维护模式有两种触发方式:

1. 自动触发

譬如Secondary上执行压缩

2. 手动触发

myapp:SECONDARY> db.adminCommand({"replSetMaintenance":true})

修改副本集的配置

添加节点

myapp:PRIMARY> rs.add("node3:27017")
myapp:PRIMARY> rs.add({_id: 3, host: "node3:27017", priority: 0, hidden: true})

也可通过配置文件的方式

> cfg={
    "_id" : 3,
    "host" : "node3:27017",
    "arbiterOnly" : false,
    "buildIndexes" : true,
    "hidden" : true,
    "priority" : 0,
    "tags" : {

    },
    "slaveDelay" : NumberLong(0),
    "votes" : 1
}
> rs.add(cfg)

删除节点

第一种方式

myapp:PRIMARY> rs.remove("node3:27017")

第二种方式

myapp:PRIMARY> cfg = rs.conf()
myapp:PRIMARY> cfg.members.splice(2,1)
myapp:PRIMARY> rs.reconfig(cfg)

注:执行rs.reconfig并不必然带来副本集的重新选举,加force参数同样如此。

The rs.reconfig() shell method can trigger the current primary to step down in some situations. 

修改节点的配置

将Secondary节点设置为延迟备份节点

cfg = rs.conf()
cfg.members[1].priority = 0
cfg.members[1].hidden = true
cfg.members[1].slaveDelay = 3600
rs.reconfig(cfg)

将Secondary节点设置为隐藏节点

cfg = rs.conf()
cfg.members[0].priority = 0
cfg.members[0].hidden = true
rs.reconfig(cfg)

替换当前的副本集成员

cfg = rs.conf()
cfg.members[0].host = "mongo2.example.net"
rs.reconfig(cfg)

设置副本集节点的优先级

cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 2
cfg.members[2].priority = 2
rs.reconfig(cfg)

优先级的有效取值是0~1000,可为小数,默认为1

从MongoDB 3.2开始

Non-voting members must have priority of 0.
Members with priority greater than 0 cannot have 0 votes.

注:如果将当前Secondary节点的优先级设置的大于Primary节点的优先级,会导致当前Primary节点的退位。

阻止Secondary节点升级为Primary节点

只需将priority设置为0

fg = rs.conf()
cfg.members[2].priority = 0
rs.reconfig(cfg)

如何设置没有投票权的Secondary节点

MongoDB限制一个副本集最多只能拥有50个成员节点,其中,最多只有7个成员节点拥有投票权。

之所以作此限制,主要是考虑到心跳请求导致的网络流量,毕竟每个成员都要向其它所有成员发送心跳请求,和选举花费的时间。

从MongoDB 3.2开始,任何priority大于0的节点都不可将votes设置为0

所以,对于没有投票权的Secondary节点,votes和priority必须同时设置为0

cfg = rs.conf()
cfg.members[3].votes = 0
cfg.members[3].priority = 0
cfg.members[4].votes = 0
cfg.members[4].priority = 0
rs.reconfig(cfg) 

禁用chainingAllowed

默认情况下,允许级联复制。

即备份集中如果新添加了一个节点,这个节点很可能是从其中一个Secondary节点处进行复制,而不是从Primary节点处复制。

MongoDB根据ping时间选择同步源,一个节点向另一个节点发送心跳请求,就可以得知心跳请求所耗费的时间。MongoDB维护着不同节点间心跳请求的平均花费时间,选择同步源时,会选择一个离自己比较近而且数据比自己新的节点。

如何判断节点是从哪个节点处进行复制的呢?

myapp:PRIMARY> rs.status().members[1].syncingTo
node3:27018

当然,级联复制也有显而易见的缺点:复制链越长,将写操作复制到所有Secondary节点所花费的时间就越长。

可通过如下方式禁用

cfg=rs.conf()
cfg.settings.chainingAllowed=false
rs.reconfig(cfg)

将chainingAllowed设置为false后,所有Secondary节点都会从Primary节点复制数据。

为Secondary节点显式指定复制源

rs.syncFrom("node3:27019")

禁止Secondary节点创建索引

有时,并不需要Secondary节点拥有和Primary节点相同的索引,譬如这个节点只是用来处理数据备份或者离线的批量任务。这个时候,就可以阻止Secondary节点创建索引。

在MongoDB 3.4版本中,不允许直接修改,只能在添加节点时显式指定

myapp:PRIMARY> cfg=rs.conf()
myapp:PRIMARY> cfg.members[2].buildIndexes=false
false
myapp:PRIMARY> rs.reconfig(cfg)
{
    "ok" : 0,
    "errmsg" : "priority must be 0 when buildIndexes=false",
    "code" : 103,
    "codeName" : "NewReplicaSetConfigurationIncompatible"
}
myapp:PRIMARY> cfg.members[2].buildIndexes=false
false
myapp:PRIMARY> cfg.members[2].priority=0
0
myapp:PRIMARY> rs.reconfig(cfg)
{
    "ok" : 0,
    "errmsg" : "New and old configurations differ in the setting of the buildIndexes field for member node3:27017; to make this c
hange, remove then re-add the member",    "code" : 103,
    "codeName" : "NewReplicaSetConfigurationIncompatible"
}
myapp:PRIMARY> rs.remove("node3:27017")
{ "ok" : 1 }
myapp:PRIMARY> rs.add({_id: 2, host: "node3:27017", priority: 0, buildIndexes:false})
{ "ok" : 1 }

从上述测试中可以看出,如果要将节点的buildIndexes设置为false,必须同时将priority设置为0。

参考

1.《MongoDB权威指南》

2. MongoDB官方文档

转载自:

https://www.cnblogs.com/ivictor/p/6804408.html

原文地址:https://www.cnblogs.com/xibuhaohao/p/11320218.html

时间: 2024-10-20 05:03:44

MongoDB 副本集的常用操作及原理的相关文章

MongoDB副本集的常用操作及原理

下面的操作主要分为两个部分: 修改节点状态 主要包括: 将Primary节点降级为Secondary节点冻结Secondary节点强制Secondary节点进入维护模式2.?修改副本集的配置 添加节点删除节点将Secondary节点设置为延迟备份节点将Secondary节点设置为隐藏节点替换当前的副本集成员设置副本集节点的优先级阻止Secondary节点升级为Primary节点如何设置没有投票权的Secondary节点禁用chainingAllowed为Secondary节点显式指定复制源禁止S

MongoDB分片集群常用操作

下架主节点: db.adminCommand({replSetStepDown : 1, force : true}) 删除节点: rs.remove("IP:PORT") 新增节点: rs.add({_id: ***, host:'IP:PORT',"key":value}) 原文地址:https://www.cnblogs.com/zhangtianyuan/p/8664203.html

mongodb副本集的内部机制(借鉴lanceyan.com)

针对mongodb的内部机制提出以下几个引导性的问题: 副本集故障转移,主节点是如何选举的?能否手动干涉下架某一台主节点. 官方说副本集数量最好是奇数,为什么? mongodb副本集是如何同步的?如果同步不及时会出现什么情况?会不会出现不一致性? mongodb的故障转移会不会无故自动发生?什么条件会触发?频繁触发可能会带来系统负载加重? Bully算法 mongodb副本集故障转移功能得益于它的选举机制.选举机制采用了Bully算法,可以很方便从分布式节点中选出主节点.一个分布式集群架构中一般

MongoDB副本集(一主两从)读写分离、故障转移功能环境部署记录

Mongodb是一种非关系数据库(NoSQL),非关系型数据库的产生就是为了解决大数据量.高扩展性.高性能.灵活数据模型.高可用性.MongoDB官方已经不建议使用主从模式了,替代方案是采用副本集的模式.主从模式其实就是一个单副本的应用,没有很好的扩展性和容错性,而Mongodb副本集具有多个副本保证了容错性,就算一个副本挂掉了还有很多副本存在,主节点挂掉后,整个集群内会实现自动切换. Mongodb副本集的工作原理客户端连接到整个Mongodb副本集,不关心具体哪一台节点机是否挂掉.主节点机负

MongoDB副本集

简介 mongodb复制(replication)是将数据同步在多个服务器的过程.主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致.复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并保证数据的安全性.复制还允许您从硬件故障和服务中断中恢复数据. 而副本集(replica set)是从mongodb 1.6 提供的新功能,比复制功能要强大一些并增加了故障自动切换和自动修复成员节点,

Mongodb副本集实现

MongoDB副本集概述 以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/ Primary节点接收客户端所有的写操作,整个副本集只会有一个primary节点.MongoDB副本集提供严格的一致性.主节点将所有的操作写入一个叫oplog的capped collection(这个collection的大小一般为磁盘剩余空间的5%,不同的系统可能不一样,详见http://docs.mongod

mongodb副本集维护

mongodb副本集维护主要工作: 1.查看副本集状态(集群状态.同步延迟.单个库的运行状态mongostate) 2.增删节点.停节点shutdown mongodb副本集集群同步机制 数据复制的目的是使数据得到最大的可用性,冗余,避免单点故障. 副本集中同一时刻只有一台服务器是可以写的,primary主库上写,从库同步数据 副本集主从复制也是异步同步的过程.slave从primary上获取日志,然后在自己身上完全顺序的执行日志记录的操作(该日志不记录查询操作,只记录更新操作).被同步的日志就

mongodb 副本集配置与说明

1,副本集的原理 副本集的原理与主从很相似,唯一不同的是,在主节点出现故障的时候,主从配置的从服务器不会自动的变为主服务器,而是要通过手动修改配置.但是副表集就不用,它会自动选出一台服务器做为主节点,从而保障系统的稳定性. 2,副本集新的主节点是怎么选举出来的呢 是通过bully算法来的,也就是一致性协议.具体如下 1):当主节点挂了后,副本集会获得其他从节点的最后更新时间与主服务做对比 2):如果所有从节点的最后更新时间都是很旧,那就选举停止 3):如果副本集中的大部分服务器挂了,包含主节点,

Mongodb副本集实现及读写分离

在前面的文章"Mongodb的主从模式搭建实例"中,我们对如何搭建一个主从结构的Mongodb服务器环境进行了简单的介绍.但是对于主从结构,Mongodb官方并不推荐我们使用了,可能是因为主从模式存在以下两个缺点: (1)主节点不可用之后,无法自动切换到从节点,无法确保业务访问的不间断性: (2)所有的读写操作都是对主节点的,造成主节点的访问压力较大: 因此,Mongodb为我们提供了另外一种推荐的使用方法,那就是使用副本集ReplicaSets.在这篇文章中简单描述一下副本集是如何实