Mongodb中Replication架构
Mongodb的高可用(HA)架构模式就是replication,replication提供了数据冗余以提高可用性,即将数据在多个servers上备份,当其中部分server失效时,集群仍可以提供服务。在mongodb中,“replica set”(复制集)即为replication模式,复制集为一组mongod实例,它们持有相同的数据集,其中一个实例为primary,用来接收客户端的write请求;其他实例为secondaries,它们从primary同步数据,以保持数据一致性,同时也可以接收客户端的read请求。集群中任何时候只会有一个primary,primary将数据变更操作写入oplog(一个特殊的collection表),那么secondaries从primary中有序的复制oplog中的记录,并在apply到本地的数据集,以此实现“数据同步”,这个机制在很多数据存储系统中都会涉及到;如果primay失效,那么集群将会选举一个secondary成为新的primary。
上图即为复制集的典型部署图,即一个primary和2个secondary,一个数据将会在整个集群的三个mongod实例中保存,这个拓扑结构也是replication HA中最小的单位。
我们还可以在复制集中增加一个(或者多个)arbiter实例(仲裁者),arbiter是一个特殊的实例,它本身不保存用户数据,它的主要作用就是和replication中其他成员(members)保持心跳连接,且持有一个投票配额,并在选举时投票。因为arbiter不持有数据,所以它不需要太多的资源开销,如果你的复制集中有偶数(even number)个members,可以考虑添加一个arbiter构成奇数(odd number),这样可以在选举primary时快速达成“多数派”。
根据上图我们可以看到,通过添加一个arbiter形成一个最小的replica set集群,其中primary和secondary持有实际数据,且负责与客户端交互,而arbiter只是负责在选举时投票,且arbiter不能成为primary(因为它未持有数据),辅助secondary选举为primary,最终让整个集群的部署更加简便。对于很多运维人员而言,构建一个replication需要三个对等的机器配置(内存、磁盘、CPU,因为mongod本身就是资源高耗型),确实比较纠结,arbiter可以“节约”一个secondary,不过事实上它却牺牲了replication的数据担保能力,这种结构,我们认为是旧时代Master-Slaver的替代形式(M-S模式已经被抛弃),不过它额外的提供了更多的特性。(参见下文)
1、异步复制(Asynchronous Replication)
Secondaries通过异步的方式从primary上复制数据变更的操作记录,即使复制集中有多个members失效,只要还能形成“多数派”(majority),那么复制操作将不会停止;即只要集群能够正常选举primary、有数据变更记录,那么均可以通过数据复制特性将primary上的数据复制到其他secondaries上。(备注,mongodb中客户端可以通过指定write concern来实现“半同步”、“全同步”等方式)
2、自动failover
当primary不能与其他的members通信(TCP链接故障)超过10秒(可修改,参看下午rs.reconfig()),那么集群将会尝试将其他的member选举为primary。
3、read操作
当从primary上读取数据时,可以保证“strict consistency”(严格一致性),默认情况下,客户端总是从primary上读取数据,不过client可以指定“read preference”将读取请求发送到secondaries。“异步复制”意味着secondaries返回的数据不能立即反映出primary的实时数据状态,比如primary上发生的insert(或者update)操作后,oplog还没有同步给secondaries,但是此时发生在secondaries上的read将不能获取相应documents的最新数据状态(直到同步结束)。
在mongodb中,client可以查询到数据可能是尚未持久的:
1)不考虑“write concern”,当write操作发生后,其他客户端可以在primary上看到write的数据变更,即使操作尚未向客户端确认。即这些write操作仍可能存在“磁盘写入失败”等丢失的风险。
2)上述中,客户端读取到的数据,有可能此后被“rolled back”。(非事务概念中的回滚,而是primary上write成功,但是没有replicate到secondaries,但是此时primary失效,这就意味着新的primary上丢失了部分数据,旧的primary转换成secondary并加入集群后,需要rolled back那些“超前”的数据并和新primary保持对齐)。
4、其他特性
复制集还支持一些其他特性,比如“多数据中心”、member权重等等,我们稍后逐个介绍。
一、Members(成员)
复制集中,mongod共有三种成员角色:primary,secondary,arbiter。如上述所述,最小的部署单位可以为“primary + secondary + arbiter”,或者为“primary” + 2个secondaries。一个复制集集群,最多支持50个members,但是最多只能有7个可以投票。
1、primary(主)
接收所有的write操作,也可以接收read请求。对于write操作,primary执行成功后,将会写入oplog,那么secondaries通过增量同步oplog并在自己的数据集中apply操作。所有的members(除arbiter)均可以接收read请求,默认情况下,read请求只会发送给primary,我们可以通过设定“read preference”将read请求转发给其他的members。
2、Secondary(辅助)
Secondary从primary上复制操作记录(oplog),最终保持与primary一致的数据集合。它的核心要素就是:持有数据的备份;不过secondary可以根据需要设定为“non-voting”(不参与投票选举,rs配置中votes = 0,参看下文)和“primary 0”(权重为0,参与投票,但是不能被选为primary)。复制集集群中至少有一个secondary。Secondaries不能接收write请求,但是可以接收read。当primary失效后,集群通过选举可以将某个secondary选举为primary。
1)可以通过将secondaries的priority设置为0,以阻止它称为primary;比如希望某个(些)secondary仅作数据备份。“Priority 0”的member不能发起选举,可以投票,和其他普通的secondary一样可以接收read请求。在多个数据中心的应用中,比如有2个数据中心A、B,其中B为容灾备份,那么它的所有的members都应该为“Priority 0”。
2)可以将secondaries设定为“hidden”,那么它将对用户Client不可见,即不接受用户的read、write请求,也无法被选举为primary,通常“hidden”的member也必须是“priority 0”,但它可以投票。
3)“Delayed”:一种特殊的member,它保存数据集,不过这个数据集是“落后于”primary一定时间的,比如落后于primary一个小时,那么它将不会包含最近一个小时内的数据;这种member在某些特殊场景下有用,比如“软件升级”、“数据清洗”、“冷备份”,就像snapshot一样,如果在最近一段时间内primary上发生了数据错误,可以通过delayed member来恢复。Delayed member除了具有“delay”选项外,它必须是“hidden”、“priority 0”。
备注:priority、hidden、votes、slaveDelay等属性可以通过rs配置指定,参见下文。
3、arbiter(仲裁者)
它本身不保存数据集,不能被选举为primary;不过arbiter可以投票(vote),当复制集中members的数量为偶数时,我们可以添加一个arbiter构成奇数,因为奇数个members在选举时(election)对达成“多数派”更加容易。尽管arbiter只需要消耗极少的系统资源,但是不要将arbiter与primary、secondaries部署在同一个物理节点上。
在production环境中,复制集通常为三个members,已经基本满足HA需要,因为mongod本身为系统资源高耗型应用,我们应该尽量避免过于复杂的部署方式。如果你需要更多的members参与,则尽可能保证members的个数为奇数,且至少有2个member保存数据;注意replication模式从根本上说并不是解决“负载均衡”、“读写分离”的方法,它是HA方案,即“自动Failover”和数据备份;尽管mongodb的secondaries可以接收read操作,但是对于流量比较高的应用而言,secondaries需要从primary上复制大量的oplog,以及执行和primary等量的write操作,事实上secondaries和primary面对相同的write压力,如果secondaries上再接收较多的read操作,可能导致secondary过载、增加数据复制的延迟。所以当mongod流量较高时,replication模式并不能起到“load balance”或者压力分流的作用,此时应该考虑另一种架构模式:sharding。
此外,复制集中的所有member都要开启journal(日志)功能,以及设置合适的oplog大小。
二、选举
当复制集初始化(initiating)或者primary失效时,都会触发选举(election),这个过程不需要人工介入。
选举过程需要消耗一些时间,在此期间,集群将不能接收write操作(即使旧的primary仍然存活,但因为“网络分区”问题导致它不能与其他secondaries通讯),所有的members(包括旧的primary)都处于只读状态,如果集群中没有“多数派”的members处于有效,那么将无法选举出primary,直到足够的member加入,此时整个复制集处于只读,无法接收write请求。
1)Heartbeats:复制集中的所有members之间都互相建立心跳连接,且每隔两秒发送一次心跳,如果未在10秒内收到回复,则此member将会被标记为“不可用”。
2)Priority比较:每个member都有权重值,默认为都为1,members倾向于选举权重最高者。上述提到,priority为0的member不能被选举为primary且不能发起选举;只要当前primary的权重最高或者持有最新oplog数据的secondaries没有比它更高的权重时,集群不会触发选举。如果一个拥有更高权重的member加入集群,则会首先catch up当前primary,然后重新发起一轮选举,并将此member选举为primary。
3)Optime:当前member已经从primary的oplog中应用的最后一个operation的时间戳(此时间戳有primary生成,在oplog中每个操作记录都有);一个member能成为primary的首要条件就是在所有有效的members中它持有最高的optime。
4)Connections:一个member要成为primary,它必须与“多数派”的其他members建立连接,如果未能与足够多的member建立连接,事实上它本身也无法被选举为primary;不过对于谁将成为priamry而言,多数派参考的是“总票数”,而不是member的个数,因为我们可以给每个member设定不同的“票数”。比如有三个member,每个member持有一票(vote),那么只要至少有2个member可以互相通信(3的多数派至少为2),即可选举;不过如果有2个member不可用,将无法选举,剩余的那个member如果是primary,那么它也将step down并成为secondary,整个复制集处于只读状态。
5)网络分区(Network Partitions):即集群中一部分members无法与其他members通讯,而分割成多个区域;因为选举是基于“多数派”(一个member需要与多数派建立连接,且票数也是多数派),所以网络分区时,无法进行选举(未能形成多数派时)。为了避免这种问题,建议将集群中的多个members分别部署在多个物理网段中。
选举触发时机:1)复制集初始化时,此时没有primary 2)一个secondary与primary失去连接,此时它将发起选举;如果多数派的secondaries均与primary失去连接,则选举即可进行成功,否则选举将会被正常的members否则(veto)。 3)primary关闭(step down)。
需要注意,“Priority 0”将无法发起选举,即使它与primary失去连接,它只能对别人的选举进行“投票”或者“否决”。
我们可以通过rs.stepDown()方法或者replSetStepDown命令来关闭primary,或者当有更高优先级的secondary加入时,或者当前primary无法与大多数members建立连接时,primary也会关闭,此后将触发新一轮的选举。此外,我们通过rs.reconfig()修改了复制集的配置后,也有可能会触发选举。当primary关闭时,它会关闭所有的客户端连接,此后客户端将无法write。
选举规则:
每个member都有一个priority属性,用来表示它们成为primary的资格,集群将会选举priority最高的member成为primary,默认情况下,所有的member的权重均为1,即它们有相同的机会成为primary。如果你倾向于某个member成为primary,可以将其priority的值设置的更高。默认情况下,每个member持有一个vote(票数),如果大多数member都选举某个member,那么它将成为primary;“Non-voting” member的vote值为0,且目前所有的member的vote值不能大于1。(即每个member只能投一票,或者不投票)
选举中否决:
所有的member都可以否决选举,包括“Non-voting”。将会在如下情况时否决选举(否决提议者):
1)如果提议选举的member不属于当前复制集(配置文件中未声明) 2)提议选举的member数据陈旧 3)提议选举的member priority比已知的其他member低 4)如果当前primary比提议选举者持有更高的optime
如果权重最高的member没有持有最高的optime,那么它将首先跟进optime最高的secondary,然后才能成为primary。
Rolled back:
前文已经提到“rolled back”:priamry失效之前,未能把write操作复制给大多数secondaires,此后选举出了新的primary,那么新的priamry也接受了部分write请求,那么当旧的priamry再次加入集群,它上面的数据有一些与当前priamry是“不对齐”的,那么旧的priamry则需要将那些“未对齐的”数据进行回滚,并与新的priamry保持数据一致。通常情况下,我们应该避免“rolled back”,因为这是一种比较危险的“数据不一致”的情况。rolled back数据被保存在“dbPath”路径下rollback目录中。
默认情况下,客户端的write concern为{w : 1}即write操作在primary上写入成功后就会向客户端返回结果,这种情况下,如果primary失效且数据尚未复制到secondaries时,会发生rolled back。为了避免rollback,客户端可以使用{w : majority},当write操作在大多数secondaries上写入成功后才会向客户端返回结果。
三、读写机制
1、write concern
默认情况下,write concern为只会在primary上提交write操作,我们可以重写这种设置将write操作提交到指定个数的secondaires上:
write concern提供了mongodb在replication模式中的数据写入保证机制,write concern强度决定了保障级别,当insert、update、delete操作持有较弱的write concern,那么write操作将会立即返回,不过在当发生异常时,较弱的concern将无法保证写入操作被持久化;较强的concern,意味着write操作需要在更多的secondaries上执行(有图可见,依次在secondaries上提交write),客户端需要更多的等待时间。mongod提供了多种级别的write concern,它们有几个重要的选项:
1)w
表示write操作在多少个members上提交成功才会向客户端返回确认信息,默认为1。值为1表示当write操作在primary上执行成功后会即返回确认信息(Ack),0表示客户端发送write操作后不需要等待任何确认信息,有点异步操作的意味,这也意味着客户端无法知道此次write请求是否在server端执行成功,当然这个级别也是write操作吞吐能力最强的;"majority"表示write操作在大多数members上执行成功后才向客户端返回确认信息;我们可以指定一个合适的<number>,表示write操作需要在指定数量的member上执行成功才会返回确认信息,此期间客户端一直等待;此外每个member还可以指定一个tag(标签),w的值可以为tag的名字,表示write操作需要在指定tag名称的members上执行成功。通常情况下,“majority”是个不错的选择,可以有效避免rolled back;如果你希望更高的插入效率,可以设置为0。(猜测:当primary将write操作发送给secondary之前,有可能触发将此write操作之前的尚未同步的oplog首先发送过去,否则会导致一些混乱)
2)j
即journal,值可以为true或者false,表示客户端是否需要等待write操作被写入journal日志的磁盘文件(flush到磁盘),写入journal日志可以保证当mongod异常退出后数据不会丢失,可以在启动时自动恢复。只需要primary节点上的jounral日志写入磁盘即可,即只对primary有效。(需要复制集中所有的member都开启journal功能,因为它们都有可能成为priamry;当j : true时要求每个write操作都会强制journal日志写入磁盘,对并发能力有一定的影响,这是一个值得权衡的参数)
3)wtimeout
指定write操作超时时间,即primary需要等待确认信息的最长时间,单位毫秒。因为write操作通过指定“w”和“j”参数后,会增加write操作的等待时间,当priamry等待其他memeber反馈信息超时后,将会向客户端返回error信息;可能操作在某些节点上已经执行成功,但mongod不会undo此操作。很遗憾,这种机制会导致一定的数据不一致性,比如客户端收到error信息,但是事实上write操作已经在某些member上执行成功了。如果不指定wtimeout值或者为0,那么客户端(包括primary)一直等待,直到满足条件(足够多的member执行成功)。
db.products.insert( { item: "envelopes", qty : 100, type: "Clasp" }, { writeConcern: { w: 2, wtimeout: 5000 } } )
2、read preference
“read preference”用来描述mongodb client如何路由read请求。默认情况下,read请求发送给primary,不过如果系统的read请求量很大,primary可能无法承载,此时需要将部分请求分散在其他secondaries上,不过从secondaries上read数据,有可能读取不到最新的数据,因为primary到secondaries的数据同步,是有延迟的。
1)primary : 默认模式,所有的read操作均在primary上。
2)primaryPreferred:read操作在primary上,如果primary失效,则从secondaries上读取数据。
3)secondary:read操作在secondary上。
4)secondaryPreferred:read操作在secondary上,如果所有的secondary失效,则从priamry上。
5)nearest:客户端会间歇性的评估它与所有members之间的网络延迟,read操作发给延迟最小的member。
对于复制集,所有的member都承担相等的write压力,因为最终每个write操作都会在所有的member上执行,如果secondary上有较高的read压力,会增加它与priamry数据同步的时间延迟,且从secondary上读取数据还有不一致的风险;如果你的应用需要数据正确性,建议使用primary模式或者primaryPreferred,否则可以考虑使用“secondary”等。
前文中提到oplog,即operation log,oplog并不是保存在普通的文件中,它是一个特殊的capped collection,用于保存所有的数据变更操作,primary将write操作执行成功,并写入oplog,此后secondaries复制并在本地应用;复制集中所有的member都有一份oplog备份,oplog保存在“local.oplog.rs”这个collection中(其中local为db名)。所有member之间都互相建立了链接,因此任何一个member均可以从其他memeber复制oplog。对于oplog中记录,在member上应用一次和应用多次,所得到的结果是一样的,即oplog中的操作是幂等的,这有点像数据库binlog的“row”模式。
当复制集中的member首次启动时,会根据默认size创建oplog,具体的size依赖于部署的操作系统配置(比如64位linux,为磁盘的5%),我们可以修改oplog的size以适合自己的应用。通常我们尽可能的保证复制集中所有的member的oplog尺寸都一样,此外,如果你的应用write量较大,可以设置较大的size,否则可以设置较小的size。(修改尺寸的方式,就是删除当前的oplog,然后在新建时指定size)
db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } )
不过在绝大多数情况下,默认的oplog尺寸基本可以满足,不过如果有如下情形,可以考虑增加size:
1)update多个document:一次update操作,更新多条(通常是数量很大)文档时;因为oplog为了保证幂等性,需要将更新的每条document最终数据状态都写入oplog,这可能导致oplog产生大量的数据。
2)delete:批量delete,基本情况同1),虽然不会导致db的数据尺寸增加,但是仍会产生大量oplog。
我们可以通过“rs.printReplicationInfo()”方法查看oplog的使用情况。
3、readConcern(3.2+版本)
mongodb 3.2+版本提供了readConcern特性,对wiredTiger引擎有效,readConcern允许客户端选择read操作的隔离级别(类似与writeConcern);可以指定此选项值为“majority”表示只读取那些已经在majority个members上写入成功的数据,以避免“rollback”的发生;也可以指定为“local”表示只要本地数据可见就能read(write操作在本地内存或者数据文件成功的,但不保证已经在replica set多个节点同步成功),不过这可能出现“rollback”(即primary失效,可能导致有些尚未同步的数据丢失,类似于“不可重复的读”)。默认此值为“local”。如果想开启“majority”需要在配置文件中新增如下配置:
replication: enableMajorityReadConcern: true
collection.withReadConcern(ReadConcern.MAJORITY).find().iterator();
四、部署
本人在单机上尝试部署3个mongod,构建一个简单的replica set集群,其中一个为priamry,两个secondaries。
#mongodb 0 port 27017 dbpath /data/mongo_0/db #mongo 1 port 28017 dbpath /data/mongo_1/db #mongo 2 port 29017 dbpath /data/mongo_2/db
1、完整配置:
systemLog: quiet: false path: /data/mongodb_0/logs/mongod.log logAppend: false destination: file processManagement: fork: true pidFilePath: /data/mongodb_0/mongod.pid net: bindIp: 127.0.0.1 port: 27017 maxIncomingConnections: 65536 wireObjectCheck: true ipv6: false storage: dbPath: /data/mongodb_0/db indexBuildRetry: true journal: enabled: true directoryPerDB: false engine: mmapv1 syncPeriodSecs: 60 mmapv1: quota: enforced: false maxFilesPerDB: 8 smallFiles: true journal: commitIntervalMs: 100 wiredTiger: engineConfig: cacheSizeGB: 8 journalCompressor: snappy directoryForIndexes: false collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true operationProfiling: slowOpThresholdMs: 100 mode: off replication: oplogSizeMB: 1024 replSetName: rs_sample
上述为mongo_0的配置,对于其他两个mongod需要修改配置中的路径,因为我们仅仅是测试用,所以oplogSizeMB参数就设置的小了一些,在production环境中需要调整的更大(比如10240),最重要的配置就是“replication”部分,它们必须有相同的“replSetName”值。创建三个配置文件“mongo_0.conf”、“mongo_1.conf”、“mongo_2.conf”放在mongodb的安装路径下。需要注意,在每个dbpath目录下,还要手动创建“db”、“logs”两个子目录,否则可能导致启动失败。
2、启动
#启动mongo 0 ./mongod -f mongo_0.conf #启动mongo 1 ./mongod -f mongo_1.conf #启动mongo 2 ./mongod -f mongo_2.conf
3、复制集初始化
#使用mongo shell连接到任意一个mongod实例,比如“mongo 0” #mongo 0 shell > ./mongo --host 127.0.0.1 --port 27017 > rs.initiate()
rs.initiate()指令就是初始化复制集,比如创建oplog、生成复制集的一些配置信息等。然后我们通过rs.conf()指令可以查看到,此时“mongo 0”(即当前mongod)默认已经成了复制集的member;members是一个JSON数组,会列举出当前复制集中所有的member以及其属性,此时我们只看到一个member,而且host信息似乎有些不太“美观”,我们可以通过如下方式修改host值,当然member的所有属性都可以通过这种方式修改:
#mongo 0 shell > cfg = rs.conf(); > cfg.member[0].host = "127.0.0.1:271071"; > rs.reconfig(cfg);
修改host时,需要注意保证复制集中其他的member能够访问,且和配置文件中绑定的地址一样(或者解析后的地址一样)。
4、新增member
#mongo 0 shell > rs.add("127.0.0.1:28017"); > rs.add("127.0.0.1:29017")
新增2个member,rs.add(String host, boolean arbiter)允许接受个参数,第一个为host,格式可以为address:port,address可以为ip地址或者域名,第二个参数为可选,表示此member是否为arbiter,默认此值为false。注意,无论何时,host名称必须与相应的member配置文件中的bind_ip参数保持一致。
此后我们可以通过rs.conf()查看当前配置,示例如下:
#mongo 0 shell rs_sample:PRIMARY> rs.conf(); { "_id" : "rs_sample", "version" : 4, "members" : [ { "_id" : 0, "host" : "127.0.0.1:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 }, { "_id" : 1, "host" : "127.0.0.1:28017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 }, { "_id" : 2, "host" : "127.0.0.1:29017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatTimeoutSecs" : 10, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 } } }
rs.add()方法执行成功后,当前mongod将会与指定的host建立连接,并开始选举primary;并且我们操作的config信息也将同步给其他members,尽管我们没有在“mongo 1”、“mongo 2”上执行任何操作,我们通过shell连接到“mongo 1”或者“mongo 2”,通过rs.conf()仍然可以查看到复制集的配置信息;因为对于修改复制集的配置而言,我们只需要在一个member上(通常为primary)操作即可,同时rs.initiate()方法也只需要在第一个member上执行一次即可。
5、其他复制集指令
1)rs.help() :输出所有的复制集有关的操作方法列表,这是一个帮助方法。
2)db.shutdownServer() :优雅关闭当前server,通常情况下我们不建议使用kill进程的方式关闭,此指令可以让mongod安全退出,不会导致数据异常。
3)rs.addArb(String host):添加一个arbiter。
4)rs.conf():输出当前复制集的配置信息。我们从上文中可见,配置信息中包含了所有的可调节参数,比如“heartbeatTimeoutSecs”、priority、w(write concern默认值)等等。
5)rs.freeze(int seconds):通常在维护时使用,如果当前mongod需要维护,比如升级、数据清洗等,freeze方法将导致当前member在指定时间内不能成为primary,即取消参选资格,但可以投票。
6)rs.initiate(Document config):初始化复制集配置信息,config参数为可选,如果没有指定config,则默认将当前mongod实例作为首个member加入配置,否则将使用指定的config。
7)rs.printSlaveReplicationInfo():输出secondaries的状态,主要是可以查看它们数据同步的情况,结果样例如下:
rs_sample:PRIMARY> rs.printSlaveReplicationInfo(); source: 127.0.0.1:28017 syncedTo: Tue Nov 03 2015 21:25:25 GMT+0800 (CST) 0 secs (0 hrs) behind the primary source: 127.0.0.1:29017 syncedTo: Tue Nov 03 2015 21:25:25 GMT+0800 (CST) 0 secs (0 hrs) behind the primary
8)rs.reconfig(Document config,boolean force) :重新配置复制集,旧的配置信息将会被覆盖。此方法需要在primary上执行;其中force为可选参数。此方法在某些情况下将会导致primary被step down,比如修改了primary的priority,或者增减了members等;当primary关闭后,其上客户端连接也会被强制关闭,并开始选举。
cfg = rs.conf(); cfg.members[1].priority = 2; rs.reconfig(cfg);
9)rs.remove(String hostname):从当前复制集中移除指定host的member,host的值必须与conf信息中的host完全一致;在移除member之前,首先需要将此member关闭。
10)rs.status():可以查看集群中每个member的状态,比如是primary还是seconday,optime,健康状况等。
11)rs.stepDown():需要在primary上执行此方法,表示关闭当前primary,并由此出发新的选举。
6、修改属性
在上文中我们通过rs.conf()能够查看复制集的配置信息,展示出所有的memebers以及【setting信息】,我们可以像修改host那样修改其他属性,比如priority、hidden类型、votes值等。
##将member[0]修改为delayed member cfg = rs.conf(); cfg.members[0].hidden = true; cfg.members[0].votes = 0; cfg.members[0].slaveDelay = 3600 ##修改复制集的setting信息 cfg.setting.getLastErrorDefaults.w = "majority"; cfg.setting.getLastErrorDefaults.wtimeout = 12000 rs.reconfig(cfg);
五、JAVA编码示例
1、pom.xml
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver</artifactId> <version>3.1.0</version> </dependency>2、java示例
List<ServerAddress> replicaSet = new ArrayList<ServerAddress>(); replicaSet.add(new ServerAddress("127.0.0.1",27017)); replicaSet.add(new ServerAddress("127.0.0.1",28017)); replicaSet.add(new ServerAddress("127.0.0.1",29017)); MongoClientOptions options = MongoClientOptions.builder().writeConcern(WriteConcern.MAJORITY) .connectTimeout(30000) .connectionsPerHost(128) .heartbeatConnectTimeout(15000) .heartbeatFrequency(10000) .maxConnectionIdleTime(60000) .maxWaitTime(10000).build(); MongoClient mongoClient1 = new MongoClient(replicaSet,options); MongoDatabase db = mongoClient.getDatabase("test");//获取DB
或者使用MongoClientUri来构建:
MongoClientURI connectionString = new MongoClientURI("mongodb://127.0.0.1:27017,127.0.0.1:28017,127.0.0.1:29017"); MongoClient mongoClient = new MongoClient(connectionString);
mongodb客户端提供了server自动发现功能,即间歇性的与每个server发送心跳以判断server是否可用,如果发现不可用,客户端将尝试与其他server建立连接,客户端也能区分出members的角色:primary还是secondary;开发者在构建MongoClient时,只能指定能够进行读写操作的host列表,如果需要调优,可以配置合适的连接池相关的options。