MongoDB实战-如何在Windows环境下管理副本集

本文详细介绍了MongoDB副本集的配置、状态监测、故障转移及恢复等关键内容,并对比了传统主从复制的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     虽然MongoDB提供了自动化功能,但副本集其实还有些潜在的复杂配置选项,接下来,我们将详细介绍这些选项。为了让配置简单一些,我也会就哪些选项是能被安全忽略的给出建议。

1. 配置细节

    这里我会介绍一些与副本集相关的mongod启动选项,以及副本集配置文档的结构

(1)  复制选项

     先前,学习了如何使用shell的rs.initiate()和rs.add()方法初始化副本集。这些方法很方便,但它们隐藏了某些副本集配置选项。这里你将看到如何使用配置文档初始化并修改一个副本集的配置。

    配置文档里说明了副本集的配置。要创建配置文档,先为_id添加一个值,要和传给-replSet参数的值保持一致。

config={_id:"mySet",members:[]}
members也是配置文档的一部分,可以像下面这样定义:

config.menbers.push({_id:0,host:'arete:40000'})
config.menbers.push({_id:1,host:'arete:40001'})
config.menbers.push({_id:2,host:'arete:40002',arbiterOnly:true})
随后,将config文档作为rs.initiate()的第一个参数,完成副本集的初始化

       严格来说,该文档应该包含以下部分:包含副本集名称的_id字段、members数组(可以指定3-12个成员),以及一个可选的子文档(用来设定某些全局变量)。示例副本集中使用了最少的配置参数,外加可选的arbiterOnly设置。

      文档中要求有一个_id字段,与副本集的名称相匹配。初始化命令会验证每个成员节点在初始化时是否都在-replSet选项里使用了这个名称。每个副本集成员都有一个_id字段,包含从0开始递增的整数,还要有一个host字段,提供主机名和可选的端口。

      这里通过rs.initiate()方法初始化了副本集,它是对replSetInitiate命令的简单封装。因此,也可以通过如下的方式启动副本集:

db.runCommand({replSetInitiate:config})
     config就是一个简单的变量,持有配置文档。一旦初始化完毕,每个集合成员都会在local数据库的system.replSet集合里保存一份配置文档的副本。如果查询该集合,你会看到该文档现在有一个版本号了。每次修改副本集的配置,都必须递增这一版本号。

     要修改副本集的配置,有一个单独的方法replSetReconfig,它接受一个新的配置文档。新文档可以添加或删除集合成员,还可以修改成员说明和全局配置选项。修改配置文档、增加版本号、以及把它传递给replSetReconfig方法,这个过程较为麻烦,所以在shell里有一些辅助方法来简化这个过程,可以用过rs.help()获取辅助方法。

     需要牢记一点,无论何时,要是重新配置副本集导致重新选举新的主节点,那么所有客户端的连接都会被关闭。这是为了确保客户端向从节点发送fire-and-forget风格的写操作。

     如希望通过驱动配置副本集,可以使用rs.add方法,可以在shell中输入rs.add来查询使用方法。

(2) 配置文档选项

     到目前为止,我们都局限在最简单的副本集配置文档里。但这些文档还支持很多选项,无论是针对副本集成员还是整个副本集。我们将从成员选项开始进行介绍。

    _id(必填):唯一的递增整数,表示成员ID。这些_id从0 开始,每添加一个成员就加1.

    host(必填):保存了成员主机名的字符串,带有可选端口号。如果提供了端口号,需用冒号与主机名分隔(例如arete:30000)。如果没有指定端口号,则默认使用端口27017。

    arbiterOnly:一个布尔值,true或false,标明该成员是否是仲裁节点。仲裁节点只保存配置数据。它们是轻量级成员,参与主节点选举但本身不参与复制。

     priority: 一个0-1000的整数,帮助确定该节点被选举为主节点的可能性。在副本集初始化和故障转移时,集合会尝试将优先级最高的节点推选为主节点,主要它的数据是最新的。也有一些场景里,你希望某个节点永远不会成为主节点(比方说:一个位于从数据中心的灾难恢复节点)。在这些情况中,可以把优先级设置为0.遇到isMaster()命令,带有优先级0的节点会被标记为被动节点,永远不会被选举为主节点。

     votes: 所有副本集成员默认都有一票。votes设置让你能给某个单独的成员更多投票。如果要使用该选项,请格外小心。首先,在各个成员的投票数不一致时,很难推测副本集的故障转移行为。其次,绝大多数生产部署环境里,每个成员只有一票的配置工作都得十分理想。因此,要是确定要修改某个指定成员的投票数,一定要经过深思熟虑,并仔细模拟各种故障场景。

     hidden:一个布尔值,如果为true,在isMaster命令生成的响应里则不会出现该节点。因为MongoDB驱动依赖于isMaster来获取副本集的拓扑情况,所以隐藏一个成员能避免驱动自定访问它。该设置能通buildIndexes协同使用,使用时必须有slaveDelay

    buildIndexes 一个布尔值,默认为true,确定该成员是否会构建索引。仅当该成员永远不会成为主节点时(那些优先级为0的节点),才能将其设置为false。该选项是为那些只会用作备份的节点设计的。如果备份索引很重要,那就不要使用它

     slaveDelay:指定从节点要比主节点延迟的秒数。该选项只能用于永远不会成为主节点的节点。所以如果把slaveDelay设置为大于0的值,务必保证将优先级设置为0。可以通过延迟从节点来抵御某些用户错误。例如,如果一个延迟30分钟的从节点,管理员不小心删除了数据库,那么问题扩散之前,你有30分钟做出反应。

     tags:包含一个任意键值对集合的文档,通常用来标识成员在某个数据中心或机架的位置。标签被用来指定写关注的粒度和读设置。

     以上是所有针对单个副本集成员的选项。还有两个全局副本集配置参数,位于settings键中。在副本集配置文档中,他们是这样的:

{
settings:{
getLastErrorDefaults:{w:1},
getLastErrorMode:{multiDC:{dc:2}}
}
}
    getLastErrorDefaults 当客户端不带参数调用getLastError时,默认的参数是由这个文档指定的。要谨慎对待该选项,因为它可能设置了驱动中getLastError的全局默认值,你想象一种情况,应用程序开发者调用了getLastError,但他没有意识到管理员在服务器上指定了一个默认值。简单起见,要指定所有写操作都要在500ms内复制到至少两个成员上。可以像这样进行配置:

settings:{getLastErrorDefaults:{w:2,wtimeout:500}}
       getLastErrorModes:为getLastError命令定义了额外模式的文档,这个特定依赖于副本集状态。

2. 副本集状态

      通过replSetGetStatus命令能够看到副本集机器成员的状态。或者在shell中通过rs.status()辅助方法。结果文档标识了现存成员及其各自的状态,正常运行时间和oplog时间。了解副本集成员的状态是非常重要的。

状态状态字符串说明
0STARTUP表示节点正在通过ping与其他节点沟通,
分享配置数据
1PRIMARY这是主节点,并且副本集中只有一个主节点
2SECONDARY这是只读从节点,该节点在故障转移时可能
会成为主节点,当且仅当其优先级大于0
并且没有被标记为隐藏时
3RECOVERING该节点不能用于读写操作,通常会在故障转移或
添加新节点后看到这个状态。在恢复时,数据文件通常正在
同步中,可以查看正在恢复的节点的日志进行验证
4FATAL网络连接仍然建立着,但节点对ping没响应了,节点被标记为
FATAL,通常说明托管该节点的机器发生了致命错误
5STARTUP2初始化数据文件正在同步中
6UNKNOWN还在等待建立网络连接
7ARBITER该节点时仲裁节点
8DOWN该节点早些时候还能访问并正常运行,但现在“心跳”检测没
应答了
9ROLLBACK正在进行回滚
当所有节点的状态都是1,2,7的时候,并且至少一个节点是主节点时,可以认为副本集是稳定且在线的。可以在外部脚本里使用replSetGetStatus命令来监控全局状态,复制延时以及正常运行时间,建议在生产环境部署中这样做。

3.故障转移与恢复

      当配置中所有成员都能和其他成员通信时,副本集就能上线了。每个节点默认都有一票投票,那些投票最终会帮助得出投票结果,选出主节点。这意味着只要有两个节点(和投票)就能启动副本集了。初始的投票数还能决定发生故障转移时,什么才能构成多数节点。

     让我们假设配置了一个由三个完整副本(没有仲裁节点)组成的副本集,这也达到了自动故障转移的推荐最小配置。如果主节点发生了故障,剩下的从节点仍能互相看到对方,那么就能选出新的主节点。如何选择呢?拥有最新oplog(或者更高优先级)的从节点会被选为主节点。
      故障模式与恢复

     恢复是在故障后将副本集还原到原始状态的过程。有两大类故障需要处理。第一类包含所谓的无损故障(clean failure),仍然可以认为该节点的数据文件是完好无损的。网络分区(network partition)就是一个例子,若某个节点失去了与其他节点的连接,你只需要等待重新建立连接就行了,被分割开的节点也会重新变为副本集中的成员。还有一个类似的情况,某个节点的mongod进行出于某些原因终止了,但它恢复正常的在线状态。同样的,一旦进程重启,就能重新加入集合了。

     第二类故障包含所有明确故障(categorical failure),某个节点的数据文件不存在或者必须假设已经损坏。非正常关闭mongod进程,又没有开启Journaling日志,以及硬盘崩溃都属于此类故障。恢复明确故障节点的唯一途径就是重新同步或利用最近的备份完全替换数据文件,让我们看下这两种策略。

    要完全同步更新,在故障节点上的某个空数据目录里启动一个mongod进程。主要主机名和端口号没有改变,新的mongod会重新加入副本集,随后重新同步全部现有数据。如果主机名或者端口号有变化,那么mongod重新上线后,你还需要重新配置副本集。举个例子,假设节点arete:40000的数据无法恢复,你在foobar:40000启动了一个新的节点。你可以重新配置副本集,只需要抓取副本集配置文档,修改第二个节点的host属性,随后将其传给rs.reconfig()方法:

use local
config=db.system.replset.findOne()
config.members[1].host="fooba:40000"
rs.reconfig(config)
     现在新节点就加入副本集了,而新节点应该能从现有节点同步数据了。

     除了通过完全重新同步进行数据恢复,还可以通过最近的备份进行恢复。通常都会使用某个从节点来进行备份方法时制作数据文件的快照并离线存储。仅当备份中的oplog不比当前副本集成员的oplog就时,才能通过备份进行恢复。也就是说,备份的oplog的最新操作必须仍存在于线上oplog里。可以使用db.getReplicationInfo()提供的信息立即确定情况是否如此。在进行恢复时,不要忘记考虑还原备份所需要的时间。要是备份里最新的oplog条目在从备份复制到新机器过程中仍可能变旧,那么最好还是进行完全重新同步吧。

     但是通过备份进行恢复速度更快,部分原因是不用从零开始重新构建索引。要从备份进行恢复,将备份的数据文件复制到mongod的数据路径里。应该会自动开始重新同步的,你可以检查日志或者运行rs.status()进行验证。

4. 部署策略

     副本集最多可以包含12个节点。提供自动故障转移的最小副本集配置就是先前构建的那个,包含两个副本和一个仲裁节点。在生产环境下,仲裁节点可以运行在应用服务器上,而副本则运行在自己的机器上。对于多数生产环境的应用而言,这种配置既经济又高效。

     但是对于那些对正常运行时间有严格要求的应用而言,副本集中需要包含三个完整的副本。那个额外的副本能带来什么好处呢。想象一下,一个节点彻底损坏了。在恢复损坏节点期间,你还有两个正常的节点可用。只要第三个节点在线并正常恢复(这可能需要几个小时),副本集仍能自动故障转移到拥有最新数据的节点上。

     一些应用程序要求有两个数据中心来做冗余,三个成员的副本集在这种情况下仍然使用。技巧在于让其中一个数据中心仅用于灾难恢复。如下图,其中,主数据中心运行了副本集的主节点和一个从节点,备用数据中心的从节点作为被动节点(优先级为0)。在这个配置中,副本集的主节点始终是数据中心A里两个节点之一。你可以在损失任意一个节点或者任意一个数据中心的情况下,保持应用程序在线。故障转移通常是自动的,除非数据中心A的节点都发生了故障。同时损失两个节点的情况很少见,通常表现为数据中心A完全故障或者网络分区。要迅速恢复,可以关闭数据中心B里的节点,不带-replSet参数进行重启。除此之外,还可以在数据中心B中重启两个新节点,随后强制进行副本集重新配置。照道理不该在大多数节点无法访问的时候重新配置副本集,但在紧急情况下可以使用force选项这么做。例如,假设定义了一个新的副本集配置config,强制重新配置使用如下方式:

rs.reconfig(config,{force:true})
       主要的还是测试工作,了解了副本集在这些状况下的表现,可以让你从容不迫地应对。

   5. 传统的主从复制

         主从复制是MongoDB最初使用的复制范式。这种复制易于配置,能支持任意数量的从节点。但是出于一些原因,我们不再推荐。首先,故障转移完全是人工操作的。如果主节点发生故障,管理员必须关闭某个从节点,然后把它重启为主节点,随后应用程序必须重新配置以指向新的主节点。其次,恢复很困难,因为oplog仅存在于主节点上,发生故障后要去在新的主节点上创建新的oplog,这意味着发生故障时,其他节点都需要从新主节点重新进行同步。

  副本集才是王道






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值