Fork me on GitHub

mongodb高可用概念篇

mongodb replset conception

Posted by Kaelzhang on December 18, 2016

img

前言

mongodb高可用实战分为概念篇和实战篇两部分内容。从概念理解到项目实践详尽介绍mongodb高可用相关内容以及如何在项目中实施。本篇为概念篇,主要负责介绍mongodb应用层面涉及高可用的相关方案,着重介绍mongodb副本集概念、特点、原理及机制。

概念篇

mongodb基础介绍

mongo-w300

MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一种基于文档类型的开源数据库。作为一个适用于敏捷开发的数据库,MongoDB的数据模式可以随着应用程序的发展而灵活地更新。与此同时,其也为开发人员 提供了传统数据库的功能包括:二级索引、完整的查询系统以及严格一致性等。

MongoDB具有可扩展、高性能和高可用等特点。它可以从单服务器部署扩展到大型、复杂的多数据中心架构。利用内存计算的优势,MongoDB能够提供高性能的数据读写操作。 MongoDB的本地复制和自动故障转移功能使产品具有企业级的可靠性和操作灵活性。

mongodb高可用方案

主从模式

主从模式是数据库传统高可用方案,也是mongodb最早支持的高可用方案。该模式采用多机备份,若主节点挂掉,从节点可以接替主机继续提供数据服务。其特点如下:

  1. 主节点是固定的,通过–master参数指定
  2. 从节点仅从主节点复制
  3. 读写都在主节点上 启动示例如下:
// 主节点启动
mongod --master

// 从节点启动
mongod --slave --source master_address

然而由于副本集模式的出现,主从模式现已较少使用。

副本集模式

副本集基本概念

副本集就是具有自动故障恢复能力的主从集群,,由一个活跃节点、若干备份节点以及一个可选的仲裁节点组成,节点总数量为奇数。 从节点的名字上就能直观反映副本集模式与主从模式的区别,副本集模式里的节点都有可能成为主节点(活跃节点就是当前的主节点),主节点是不固定的。而主从模式的主节点是固定不变的。 活跃节点用于处理客户端读写请求,备份节点用于保存主服务器的数据副本,仲裁节点(稍后介绍)用于保障选举出主节点。这些节点都承载有mongod实例的服务器,活跃节点和备份节点共享相同的数据集,其特点如下:

  1. 所有东西都是自动化,例如:活跃节点自动提升、自动故障恢复等。
  2. 主节点不固定,无需人为指定。
  3. 写在主节点,读可分配到备份节点,实现读写分离。

副本集示例

下面这张图是一个典型三节点副本集,由一个活跃节点,两个备份节点组成。活跃节点接受所有的写操作,其上数据集的所有变更都会记录到自身的操作日志(oplog)中。 replica-set-read-write-operations-primary

备份节点复制活跃节点的的oplog,然后将oplog的操作应用到自身的数据集上,以达到与活跃节点数据一致的目的,如下图所示: replica-set-primary-with-two-secondaries 此外,副本集内部节点每2秒会相互发送心跳包。

自动故障迁移

如果活跃节点不可用,备份节点之间会自动发起选举将其中一个成员升级为新的活跃节点,如下图所示: replica-set-trigger-election 其特点如下:

  1. 触发时机:活跃节点超过10秒都没有与其他节点发起心跳。
  2. 备选节点推选自身为活跃节点,并在大多数节点同意后成为活跃节点。
  3. 整个过程耗时将近1分钟。(发现不可用10~30秒,选举过程10~30秒)

选举机制

bully election mongodb选举算法采用的是bully算法(如上图所示,当5号节点不可用时,选举4号节点成为主节点的过程),该算法是一种相对简单的协调者竞选算法,mongodb用这个算法来选举副本集中的活跃节点。该算法具有以下特点:

  1. 节点必须得到大多数的支持才能成为活跃节点,失去大多数支持就立刻变成普通的备份节点
  2. 当一个节点与活跃节点的无法连接的时候,它就会推举自己成为活跃节点,并且需要接受其它节点的考核,考核内容有:该节点的数据是不是最新,该节点的优先级是不是最高等等。如果通过考核则该节点就会成为活跃节点。
  3. 每个节点只能推举自己作为活跃节点,不可以推荐其他节点成为活跃节点。
  4. 当所有节点都无法获得大多数节点支持的时候,副本集中将会没有活跃节点,此时副本集将处于不可用状态。
与raft算法的差异

对分布式一致性算法有所了解的同学是不是觉得很像raft算法呢?其实mongodb的选举算法就是根据mongodb的实际需求从raft演进而来的,其差异如下:

  1. raft使用强领导模型。领导负责管理从主节点到其他节点的复制和数据流。而在MongoDB副本集中,从节点遵循上游节点的操作日志(oplog),上游节点可以是主节点,也可以是具有较新oplog的从节点。
  2. raft只有三个节点状态要考虑:领导(主),随从(从)以及候选者(选主)。 MongoDB有其他节点状态要考虑,包括更多的潜在错误状态,如RECOVERING节点、SHUNNED节点及延迟节点等。
  3. 在raft中,每个选举期间每个节点只能为候选节点投一次票。 MongoDB可将节点投票存为副本集配置中,因此节点即可以不投票也可以多次投票。
  4. raft使用联合共识方法,允许集群在配置更改期间继续操作。 MongoDB在选举过程中,由于副本集没有主节点,所以不能写入数据。
选举触发条件

选举有三个触发条件:

  1. 初始化一个副本集时
  2. 主节点和副本集断开连接(可能是网络问题)
  3. 主节点宕机
选举角色和状态

在选举过程中,节点根据其状态可分为两类角色:有选举权节点和无选举权节点,如下图有7个有选举权节点和2各无选举权节点。 replica-set-only-seven-voting-members

  1. 有选举权节点:votes属性为1且该节点状态为以下5种状态之一:
    • PRIMARY:该状态表明节点是活跃节点,且状态正常。
    • SECONDARY:该状态表明节点是备份节点,且状态正常。
    • RECOVERING:这个状态表明节点运转正常,但是暂时还不能处理请求,当一个节点与其他节点失联时也会进入这个状态。
    • ARBITER:仲裁者应该始终处于这个状态。
    • ROLLBACK:当成员正在执行回滚操作时。
  2. 无选举权节点:votes属性为0的节点,尽管这类节点在选举中无权投票,但这些成员拥有副本集数据的副本,可接受来自客户端的读取操作。另外,此类节点也可以被选举为活跃节点。

节点状态

除了上文已经介绍过的PRIMARY、SECONDARY、RECOVERING、ARBITER及ROLLBACK五种常见节点状态外,还有下面六种特殊状态:

  1. STARTUP:刚加入到复制集中,配置还未加载。
  2. STARTUP2:配置已加载完,初始化状态。
  3. DOWN:节点不可到达。
  4. UNKNOWN:未获取其他节点状态而不知是什么状态,一般发生在只有两个成员的时候。
  5. REMOVED:移除复制集。
  6. FATAL:出错。查看日志grep “replSet FATAL”找出错原因,重新做同步。

仲裁节点

仲裁节点不储存数据,主要用于凑数,假如该副本节点是偶数个,当每一方都一样都凑不够大多数的情况下,仲裁节点有决定性的一票,可以通过addArb()添加总裁节点,需要注意仲裁节点是不可逆的反之亦然。并且如果考虑节点应该作为仲裁节点还是副本节点的时候最好作为副本节点,如果是副本数是偶数的时候才考虑使用仲裁节点,如果副本数是奇数时使用仲裁节点将是一个很坏的打算。 replica-set-primary-with-secondary-and-arbite 仲裁节点参与选举示例: replica-set-four-members-add-arbite

隐藏节点

隐藏节点就是hidden属性为true且优先级为0的节点。客户端不会向隐藏成员发送读写请求,隐藏成员默认也不会作为复制源(当其它复制源不可用时,它才会被使用的)。因此,可以将一些性能一般的服务器或备份服务器做为隐藏节点隐藏起来。客户端的driver是使用rs.isMaster()命令来探测节点的,而该命令不会返回隐藏节点,以达到节点隐藏的目的。但是可以通过rs.status()和rs.config()看到隐藏节点。另外节点隐藏是可逆的,也就是可以将hidden属性设置为false来让节点可见。 注:隐藏节点与仲裁节点比较容易混淆,其差异还是在于隐藏节点在极端情况下还是可能成为复制源的。而仲裁节点则不会成为复制源,仅参与选举投票。

延迟备份节点

延迟备份节点是实现副本集延迟复制功能的基础。当数据库遭到毁灭性破坏时(如:由于人为疏忽被不小心删除),延迟备份节点在主节点被删除后还能保留之前的数据,以便将数据从破坏中恢复过来。通过slaveDelay参数将备份节点设置为延迟备份节点,另外其必须是隐藏节点。 replica-set-delayed-membe 上图是一个包含5个节点的副本集,所有节点自身都拥有一套数据备份。灰色的备份节点就是一个延迟备份节点,它在复制活跃节点的oplog操作后,会延迟3600秒(1小时)应用到自身数据。

读写分离模式

replica-set-read-preference 有时候为了减轻活跃节点的压力,可以给mongodb副本集设置特定的读偏好。有以下5种模式可选:

  1. primary:默认模式,读操作只在活跃节点,如果活跃节点不可用,报错或者抛出异常。
  2. primaryPreferred:首选活跃节点,大多情况下读操作在活跃节点,如果活跃节点不可用,如故障转移,读操作在备份节点。
  3. secondary:读操作只在备份节点, 如果备份节点不可用,报错或者抛出异常。
  4. secondaryPreferred:首选备份节点,大多情况下读操作在备份节点,特殊情况(如单节点架构)读操作则会在活跃节点。
  5. nearest:最邻近节点,读操作在最邻近的成员,可能是活跃节点,也可能是备份节点。

需要注意的是除了primary模式外,其他模式都可能会读到脏数据。

参考文献

  1. 《Mongodb权威指南》
  2. 《Mongodb官方文档》
  3. 《mongodb复制—创建副本集》

  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!