MongoDB系列-解决面试中可能遇到的MongoDB复制集(replica set)问题

  MongoDB复制集(replica set):MongoDB复制集维护相同数据集的一组mongod进程,复制集是生产部署的基础,具备数据冗余以及高可用性。node

那为何要设置复制集(replica set)呢?mongodb

  • 因为复制集是经过在不一样服务器上保存来副本,可保证数据在生产部署的冗余和可靠性,不会由于单点问题而丢失数据。
  • 能够经过访问不一样服务器副本数据来提升数据读取能力,从而提升整个系统的负载能力。

1. 复制集架构原理

    副本集包含多个数据节点可选的一个仲裁节点。 而在数据节点中:只有一个主节点(primary node),其余节点为为从节点(secondary nodes)
  各个节点成员经过心跳机制进行通讯,当主节点与从节点的通讯的时间超过配置的electionTimeoutMillis期间(默认为10秒)时,符合条件的从节点要求选举将本身指定为新主节点,群集尝试完成新主节点的选举并恢复正常操做。数据库

主节点: 副本集只能有一个主节点可以确认写入操做来接收全部写操做,并记录其操做日志中的数据集的全部更改(记录在oplog中)。

oplog: 它保存了修改存储在数据库中的数据的全部操做的滚动记录,MongoDB在主节点服务器上应用数据库操做,而后在主节点服务器的oplog上记录操做,而后从节点成员在异步过程当中经过心跳机制从任何其余成员导入oplog并应用这些操做,oplog中的每一个操做都是幂等的。全部副本集成员都在local.oplog.rs集合中包含oplog的副本,这容许它们维护数据库的当前状态。服务器

从节点: 复制主节点的oplog并将oplog记录的操做应用于其数据集,若是主节点宕机了,将从符合条件的从节点选举选出新的主节点,。 并且你能够经过配置实现特定的功能,好比:网络

  • 防止从节点成为选举中的主节点Primary,指定节点优先级。
  • 阻止应用程序从节点读取数据,从而容许应用程序运行须要与正常流量分离的应用程序,隐藏节点。
  • 保留正在运行的“历史”快照,以用于从某些错误中恢复,例如无心中删除的数据库,延迟节点

仲裁节点: 仲裁节点不维护数据集。 仲裁节点的目的是经过响应其余副本集节点的心跳和选举请求来维护副本集中的仲裁。 由于它们不存储数据集,因此仲裁节点能够是提供副本集仲裁功能的好方法,其资源成本比具备数据集的全功能副本集成员更便宜。 若是您的副本集具备偶数个成员,请添加仲裁节点以得到主要选举中的大多数投票。并且仲裁节点老是只有1次选举投票,所以容许副本集具备不均匀的投票成员数,而没有复制数据的额外成员的开销。架构

心跳机制(Hearbeat): 复制集成员间默认每2s会发送一次心跳信息,若是10s未收到某个节点的心跳,则认为该节点已宕机不能够访问;若是宕机的节点为Primary,Secondary(前提是可被选为Primary)会发起新的Primary选举。仲裁人与其余集合成员之间的惟一沟通是:选举期间的投票,心跳和配置数据,并且这些交换未加密。

数据同步: 为了维护共享数据集的最新副本,副本的从节点设置同步或复制来自其余节点的数据。 MongoDB使用两种形式的数据同步:初始化同步新节点同步完整的数据集,以及整个集群节点同步后续数据更改。异步

其中,初始化同步(Initial Sync)过程:分布式

  • 克隆除本地数据库以外的全部数据库。 要进行克隆,mongod会扫描每一个源数据库中的每一个集合,并将全部数据插入到这些集合的本身的副本中。 初始同步会在为每一个集合复制文档时构建全部集合索引。 在早期版本的MongoDB中,在此阶段仅构建_id索引。学习

  • 初始同步在数据复制期间提取新添加的oplog记录。 确保目标成员在本地数据库中有足够的磁盘空间,以便在此数据复制阶段的持续时间内临时存储这些oplog记录。ui

  • 将全部更改应用于数据集。 使用来自源的oplog,mongod更新其数据集以反映副本集的当前状态。 初始同步完成后,成员从STARTUP2转换为SECONDARY。

2. 标准复制集架构

  标准复制集架构由三台服务器,其中包括三个数据节点(一个主节点、两个从节点)或两个数据节点(一个主节点、一个从节点)和一个仲裁节点两种状况。以下所示:

三个数据节点:

  • 一个主节点;
  • 两个从节点,主节点宕机后,有机会选举成为主节点。

当主库宕机后,两个从库都会进行竞选,其中一个变为主库,当原主库恢复后,做为从库加入当前的复制集群便可。

两个数据节点以及一个仲裁节点:

  • 一个主节点;
  • 一个从节点,有机会被选举成为主节点;
  • 一个仲裁节点,只有投票权利。

当主节点不可用时,将会选择从节点成为主Primary,主节点恢复后,将其做为从节点加入到现有的复制集群中便可。

3. 节点类型

优先级0型(Priority 0)节点

  优先级0型节点不能够成为成为主节点,也不能触发选举。将从节点配置为优先级为0以防止它成为主节点,这在多数据中心部署中特别有用,在许多状况下,您无需将备用数据库设置为优先级0.可是,在具备不一样硬件或地理分布的副本集中,优先级为0的备用数据库可确保仅某些成员成为主数据库,这样能够根据实际网络分区的网络质量等实际状况进行配置。

例如,一个数据中心承载主数据中心和辅助数据中心:

将第二个数据中心节点优先级为0只能为从节点数据库,而数据中心1中的节点才能成为主节点数据库。(好比你跨机房A、B部署了一个复制集,而且想指定Primary必须在A机房,这时能够将B机房的复制集成员Priority设置为0,这样Primary就必定会是A机房的成员),

隐藏型(Hidden)节点

隐藏型(Hidden)节点:

  • 隐藏型从节点是维护主数据集的副本,但对客户端应用程序不可见。隐藏型从节点适用于具备与副本集中其余成员不一样的使用模式。
  • 隐藏型从节点必须始终优先为0型从节点,所以不能成为主节点。 隐藏型从节点可能会在选举中投票。
  • 隐藏型从节点将不会收到来自应用程序的请求。咱们能够将隐藏型从节点专用于报表节点或是备份节点。

延迟型(Delayed)节点

  因为延迟型从节点是数据集的“滚动备份”或运行“历史”快照,所以它们能够帮助您从各类人为错误中恢复。 例如,延迟节点能够从不成功的应用程序升级和操做员错误(包括丢弃的数据库和集合)中恢复。并且延迟型从节点必定是优先级为0的从节点,也是隐藏型从节点。不能成主节点,也不能给客户端查询。

在选择延迟量时,请考虑延迟量:

  • 必须等于或大于预期的维护窗口持续时间。
  • 必须小于oplog的容量。

投票型(Vote)节点以及不可投票节点

  复制集节点能够经过配置members[n].votes来决定该节点是否具备投票权利!members[n].votes值为1具备投票权利为投票型节点,为0则不能够投票即为不可投票节点。无表决权的节点必须优先级为0,也是优先级大于0的成员不能为0值。虽然无表决权的成员不在选举中投票,但这些成员持有副本集数据的副本,而且能够接受来自客户端应用程序的读取操做。

另外在副本集最多可包含50个成员,但只有7个投票成员,所以非投票成员容许副本集具备7个以上的成员。并投票成员只有具有如下状态能够进行投票:

  • PRIMARY
  • SECONDARY
  • STARTUP2
  • RECOVERING
  • ARBITER
  • ROLLBACK

配置:

{
   "_id" : <num>,
   "host" : <hostname:port>,
   "arbiterOnly" : false,
   "buildIndexes" : true,
   "hidden" : false,
   "priority" : 0,
   "tags" : {
},
   "slaveDelay" : NumberLong(0),
   "votes" : 0
}
复制代码

4. 部署结构:

最大投票成员为数量
  副本集最多可包含50个成员,但只有7个投票成员。 若是副本集已有7个投票成员,则其余成员必须是非投票成员。

部署奇数个成员
  副本集应该确保具备奇数个投票成员,若是您拥有偶数个投票成员,请部署仲裁节点,以便该集合具备奇数个投票成员。仲裁节点不存储数据的副本而且须要更少的资源。 所以,您能够在应用程序服务器或其余共享进程上运行仲裁程序。 容错能力
  副本集的容错是当变为不可用的成员数,而且仍然在副本集中留下足够的节点成员来选择主节点成员。容错是副本集大小的影响, 见下表:

Number of Members Majority Required to Elect a New Primary Fault Tolerance
3 2 1
4 3 1
5 3 2
6 4 2

所以能够得出,将成员添加为偶数个到副本集并不老是会增长容错能力。可是,在这些状况下,其中将其中一个节点设置成隐藏型和延迟型从节点能够为专用功能提供支持,例如备份或报告。

提升读负载能力
  在具备很是高读取流量的部署中,您能够经过将读取分发给从节点来提升读取吞吐量。 随着部署的增加,将节点添加或移动到备用数据中心以提升冗余和可用性。

副本集分布在两个或更多数据中心
副本集分布在两个或更多数据中心的优点:

  • 若是其中一个数据中心发生故障,数据仍可用于读取。
  • 若是具备少数成员的数据中心发生故障,则副本集仍能够提供写操做以及读操做。可是,若是具备大多数成员的数据中心发生故障,则副本集将变为只读。

在不一样地域部署数据节点(具备备用的数据中心)
  要在数据中心发生故障时保护您的数据,请在备用数据中心至少保留一个成员。 若是可能,使用奇数个数据中心,并选择一个成员分布,以最大限度地提升即便丢失数据中心的可能性,剩余的副本集成员能够造成能够造成“大多数”选取出主节点,并有提供数据的副本的能力。为确保主数据中心的节点在备用数据中心的成员以前被选为主要成员,请将备用数据中心中节点members[n].priority 设置为低于主数据中节点,以下所示:

根据部署结构部署复制集示例 三个节点成员的副本集,成员合理分布以及解析以下

  • 两个数据中心:数据中心1的两个成员和数据中心2的一个成员。若是副本集的其中一个成员是仲裁者,则将仲裁者分配给具备数据承载成员的数据中心1。
  • 若是数据中心1关闭,则副本集将变为只读。
  • 若是数据中心2关闭,则副本集仍然可写,由于数据中心1中的成员能够进行选举。
  • 三个数据中心:一个成员到数据中心1,一个成员到数据中心2,一个成员到数据中心3。
  • 若是任何数据中心发生故障,副本集仍然可写,由于其他成员能够举行选举。

五副节点成员的副本集,成员合理分布以及解析以下:

  • 两个数据中心:数据中心1的三个成员和数据中心2的两个成员。
  • 若是数据中心1关闭,则副本集将变为只读。
  • 若是数据中心2关闭,则副本集仍然可写,由于数据中心1中的成员能够建立多数。
  • 三个数据中心:数据中心1的两个成员,数据中心2的两个成员和数据中心3的一个成员。
  • 若是任何数据中心发生故障,副本集仍然可写,由于其他成员能够举行选举。

高可用
集群具备自主选举能力,影响选取的因子和条件有如下:

  • 选取协议
  • 心跳机制:复制集成员间默认每2s会发送一次心跳信息,若是10s未收到某个节点的心跳,则认为该节点已宕机不能够访问;若是宕机的节点为Primary,Secondary(前提是可被选为Primary)会发起新的Primary选举。
  • 节点优先权:每一个节点都会倾向于投票给优先级最高的节点,优先级为0的节点不能成为主节点Primary,也不会主动发起Primary选举。当Primary发现有优先级更高Secondary,而且该Secondary的数据落后在10s内,则Primary会主动降级,让优先级更高的Secondary有成为Primary的机会。
  • 丢失数据中心:使用分布式副本集,数据中心的丢失可能会影响其余数据中心或数据中心中其他成员选择主数据库的能力。若是可能,在数据中心之间分发副本集成员,以最大限度地提升即便丢失数据中心的可能性,其他一个副本集成员也能够成为新的主要成员。
  • 网络分区:只有跟大多数投票节点间能保持网络畅通,才有机会被选主节点Primary;若是Primary与大多数的节点失去联系,Primary会主动降级为Secondary。当发生网络分区时,可能在短期内出现多个Primary,故Driver在写入时,最好设置『大多数成功』的策略,这样即便出现多个Primary,也只有一个Primary能成功写入大多数。

5. Write concern和Read Preference

5.1 Write concern

  Write concern描述了在操做返回成功以前必须确认写操做的数据承载成员(即主节点成员和从节点成员,但不是仲裁者)的数量。成员只能在收到并成功应用写入后才能确认写入操做。
对于副本集,默认的w:1的Write concern 要求在返回Write concern确认以前,只有Primary主节点确认写入。您能够指定一个大于1的整数值,以要求来自主节点的确认以及知足指定值所需的多个从节点,最多为副本集中数据承载成员的总数。

  Client 发出带有须要写入请求的写入操做Write concern将等待直到主节点接收来自指定须要写入询问全部数量的成员的确认。对于大于1或w:“majority ”的写入咨询 Write concern,主节点接收到所需的从节点数量在返回确承认写入答复通知client确认写入。对于w:1的写入咨询Write Concern,主要能够在本地应用(单机模式)写入时当即返回可写入答复,由于它有资格对所请求的Write Concern作出判决。

  指定超时等待写入咨询Write concern的写操做仅表示所需数量的副本集成员未在wtimeout时间段内确认写操做。它不必定表示主节点Primary未能应用写入。

检验写操做
在insert()方法中增长write Concern选项,并指定“大多数”写入关注和5秒超时,以便操做不会无限期地阻塞,以下:

db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)
复制代码

  例如,在3个节点成员的副本集中,操做将须要来自3个成员中的2个的确认。若是稍后缩放副本集以包括两个额外的投票节点,则相同的操做将须要来自5个副本集成员中的3个的确认。若是主节点服务器未在wtimeout限制内返回写入咨询 Write concern确认,则写入操做将失败并出现写入问题错误。

修改默认Write Concern
  能够经过在副本集配置中设置settings.getLastErrorDefaults设置来修改副本集的默认写入问题。配置在返回以前等待写操做(在大多数投票成员上确认后)操做命令:

cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
复制代码

5.2 Read Preference

  Read Preference是mongodb如何将读操做分配到节点中,默认状况下,应用程序将其读取操做定向到副本集中的主要成员(即读取首选项模式“primary”)。 可是,客户端能够指定读取首选项以将读取操做发送到辅助节点。Read Preference 模式以下:

  • primary: 默认规则,全部读请求发到Primary
  • primaryPreferred: Primary优先,若是Primary不可达,请求Secondary
  • secondary: 全部的读请求都发到secondary
  • secondaryPreferred:Secondary优先,当全部Secondary不可达时,请求Primary
  • nearest:读请求发送到最近的可达节点上(经过ping探测得出最近的节点)

如下是使用读取首选项模式的常见用例:

  • 为地理分布的应用程序提供本地读取。
  • 若是您在多个数据中心中安装了应用程序服务器,则能够考虑使用地理位置分散的副本集并使用非主要或最近的读取首选项。 这容许客户端从最低延迟成员读取,而不是始终从主要成员读取。
  • 在故障转移期间维护可用性。
  • 若是但愿应用程序在正常状况下从主数据库读取,则容许使用primaryPreferred,但在主数据库不可用时容许从辅助服务器读取过期的数据。 这为故障转移期间的应用程序提供了“只读模式”。

最后可关注公众号,一块儿学习,天天会分享干货,还有学习视频领取!

相关文章
相关标签/搜索