首页 » MongoDB实战 » MongoDB实战全文在线阅读

《MongoDB实战》8.1 复制概述

关灯直达底部

复制就是在多台服务器上分布并管理数据库服务器。MongoDB提供了两种复制风格:主从复制和副本集。两种方式都是在一个主节点进行写操作(写入的数据被异步地应用到所有从节点上),并从节点上读取数据。

主从复制和副本集使用了相同的复制机制,但是副本集还能保证自动故障转移:如果主节点由于某些原因下线了,可能的话,会自动将一个从节点提升为主节点。副本集还提供了其他增强,比如更易于恢复和更高级的部署拓扑。出于这些原因,现在已经没什么有说服力的理由使用简单的主从复制了。1副本集也因此是生产部署环境的推荐复制策略;因此,本章的大部分内容都是副本集的说明和例子,对主从复制只做了一个简单的概述。

1. 只有一种情况需要选择MongoDB的主从复制,即需要超过11个从节点时,因为副本集不能包含12个以上的成员。

8.1.1 为什么复制很重要

所有数据库都对其运行环境中的故障很敏感,而复制提供了一种抵御故障的机制。这里所指的故障都有哪些?下面是一些常见场景。

  • 应用程序与数据库之间的网络连接丢失。

  • 计划停机,但服务器没有按照预定计划重新上线。任何机构的服务器都一定会安排偶尔停一下机,而其停机结果不太好预测。一次简单的重启至少能让数据库服务器下线几分钟,但问题是重启完成之后又会发生什么呢?新安装的软件或硬件经常会让操作系统无法正常启动。

  • 断电。虽然大多数现代化数据中心都提供了冗余电源,但无法避免数据中心内部的用户错误、大范围局部暂时限制用电或者停电造成数据库服务器关闭。

  • 数据库服务器硬盘故障。硬盘通常都只有几年的平均无故障时间,它比你想象的更容易发生故障。2

2. 可以在谷歌的“Failure Trends in a Large Disk Drive Population”(http://research.google.com/archive/disk_failures.pdf)中看到硬盘故障率的详细分析。

除了抵御外部故障,复制对于MongoDB的耐久性来说也很重要。如果运行时没有开启Journaling日志,遇到非正常关闭,无法保证MongoDB的数据文件不受破坏。没有Journaling日志,就必须时刻运行复制,这才能确保在一个节点意外关闭时能有一份数据文件的正确副本。

当然,就算 开启了 Journaling日志也应该使用复制,毕竟你追求高可用性和快速故障转移。此时Journaling日志会迅速完成恢复,因为只需简单地回放Journaling日志就能让故障节点重新上线。相比从现有副本 重新同步 (resyncing)或手动复制副本的数据文件,这要快得多。

无论是否开启Journaling日志,MongoDB的复制功能都会极大地增强整个数据库的可靠性,因此强烈推荐使用该功能。

8.1.2 复制的使用场景

你可能会感到很惊讶,复制数据库的用途居然能有这么多。尤其是复制能帮助进行冗余、故障转移、维护以及负载均衡。下面,让我们简单地看一些使用场景。

复制主要是用来做冗余的。本质上要保证复制节点与主节点保持同步。这些副本可以和主节点位于同一数据中心里,也可以分布在不同地理位置用于容灾。因为复制是异步的,任何节点间的网络延迟或分区(partition)都不会影响主节点的性能。作为另一种形式的冗余,复制节点也可以与主节点保持一定的延时,万一用户无意间删除了一个集合,或者应用程序不知怎么的破坏了数据库,这还能提供一些防御措施。一般情况下,这些操作都会被立即复制;延时副本让管理员有时间做出反应,也许还能挽救他们的数据。

有一点很重要:虽然它们是一种冗余,但副本不是备份的替代品。备份是数据库在过去某个特定时间的快照,但副本总是最新的。在一些情况下,数据集过大让备份显得不切实际,但通常来说,备份是种明智的做法,就算用了复制也推荐进行备份。

复制的另一个使用场景是故障转移。你希望系统高可用,但仅在拥有冗余节点,并且在紧急情况下能切换到这些节点时,才能实现高可用。MongoDB的副本集通常都能方便地自动实现这种切换。

除了提供冗余与故障转移,复制还可以简化维护工作,它允许你在主节点以外的节点上执行开销很大的操作。例如,通常都会在从节点上进行备份,不给主节点带来额外的负载,避免停机。另一个例子是构建大索引,因为构建索引的开销很大,可以先在某个从节点上构建索引,然后主从切换,再在新的从节点上构建索引。

最后,复制能让你在副本间均衡读负载。对于那些读负载占绝对比重的应用程序而言,这是扩展MongoDB最简单的途径。话虽如此,但如果出现以下场景,请不要用从节点来扩展读操作。

  • 所分配的硬件无法处理给定的负载。以我上一章里提到的工作集为例,如果使用的工作数据集远大于可用内存,那么向从节点发送随机读请求仍然可能造成大量磁盘访问,导致慢查询。

  • 读写比超过50%。诚然,这个比例有点主观,但将它作为起始值还是挺合适的。此处的问题是主节点上的所有写操作最终也会写入从节点,把读操作导向正在处理大量写入的从节点有时会减缓复制过程,并不会提高读吞吐量。

  • 应用程序要求一致性读。从节点的复制是异步进行的,因此无法保证一定能读到主节点上最新写入的数据。在某些极端情况下,从节点可能延迟几个小时。

因此,你能通过复制来均衡读负载,但仅限于特定场景。如果需要进行扩展,又出现了以上某种情况,那么你需要不同的策略,包括分片、升级硬件或两者兼而有之。