标签:基本 高可用性 报告 多线程 成员 而不是 部署 cells 上进
一、副本集基本概念
副本集(replica set)
MongoDB的replica set是一个mongod进程实例簇,数据在这个簇中相互复制,并自动进行故障切换。
MongoDB的数据库复制增加了冗余,确保了高可用性,简化了管理任务如备份,并且增加了读能力。大多数产品部署都使用了复制。MongoDB中primary处理写操作,其它进行复制的成员则是secondaries。
一个副本集可以最多支持12个成员,但是只有7个成员可以参与投票。
注:MongoDB同时提供了传统的master/slave复制,这种复制的操作方法与副本集相同,但是master/slave复制不支持自动故障切换。很容易理解,主备模式下,cli端是指定了地址和端口进行mongodb的访问的,而副本集模式则是通过访问mongos来隐藏动态切换的。
成员配置
成员可以是以下某种角色:
|
成为primary |
对客户端可见 |
参与投票 |
延迟同步 |
复制数据 |
Default |
√ |
√ |
√ |
∕ |
√ |
Secondary-Only |
∕ |
√ |
√ |
∕ |
√ |
Hidden |
∕ |
∕ |
√ |
∕ |
√ |
Delayed |
∕ |
√ |
√ |
√ |
√ |
Arbiters |
∕ |
∕ |
√ |
∕ |
∕ |
Non-Voting |
√ |
√ |
∕ |
∕ |
√ |
表:副本集角色属性
故障切换恢复
副本集能够自动进行故障切换恢复。如果primary掉线或者无反应且多数的副本集成员能够相互连接,则选出一个新的primary。
在多数情况下,当primary宕机、不可用或者是不适合做primary时,在没有管理者干预的几秒后会进行故障切换。
如果MongoDB部署没有如预期那样进行故障切换,则可能是下面的问题:
Rollback
多数情况下,回滚操作可以优雅的对不能进行故障切换恢复的情况进行恢复。
Rollbacks操作发生在primary处理写操作,但其它成员没有成功的进行复制之前primary掉线时。当先前的primary开始复制 时,则表现出rollback。如果操作复制到其它成员,该成员可用,并且可以和大多数的副本集连接,则没有rollback。
Rollbacks删除了那些没有进行复制的操作,以保证数据集的一致性。
选举(Elections)
当任意的故障切换发生,都会伴随着一个选举的出现,以此来决定哪个成员成为primary。
选举提供了一种机制,用于副本集中的成员无需管理员的干预,自动的选出一个新的primary。选举可以让副本集快速和坚决的从故障中恢复。
当primary变为不可达时,secondary成员发起选举,第一个收到大多数选票的成员成为新的primary。
成员优先级
在副本集中,每个成员都有优先级,它可以帮助决定选举出primary。默认情况下,所有的成员的优先级都为1。
一致性
在MongoDB中,所有针对于primary的读操作都与最后的写操作结果相一致。
如果客户端配置了读选项以允许secondary读,读操作能从没有近期复制更新或操作的secondary成员返回结果。在这种情况下,查询操作可能返回之前的状态。
这种行为有时称为最终一致性,因为secodary成员的状态最终都会是primary的状态。MongoDB不能保证从secondary成员的读操作的强一致性。
没有办法保证从secondary成员读的一致性,除非在配置时保证写操作成功的在所有节点上都执行成功后才返回成功。
二、副本集架构和部署模式
架构
副本集部署的架构对其容量和性能都有很大影响。大多数产品部署成包含3个优先级为1 的成员就足够了。
当开发一个副本集架构时要注意下面的因素:
部署策略
不存在一个理想的副本集架构可以满足任意部署环境。
最小的副本集推荐架构为三成员集合,其中一个为primary,另外两个为secondary,secondary在一定情况下可以成为primary。
如果副本集中的成员多于三个,则需要遵照下面的架构条件:
地理上的分布式集
一个基于地理的分布式副本集可以应对一个数据中心恢复失败的情况。这种集合至少包含了一个在备份数据中心的集合成员。
图:基于地理上的分布式副本集
如果primary掉线,则副本集选出一个新的primary;如果主数据中心和备数据中心连接失败,备数据中心的secondary不能成为primary。如果主数据中心失败,则需要人为的从备数据中心恢复数据。
值得注意的是,这种架构下,必须注意在主数据中心要保持奇数个参与投票的成员,上图中则需要在主数据中心添加一个仲裁者。
非生产者成员
在有些时候,我们可能想有一个成员能够拷贝整个的数据集,但并不使其成为primary。这种成员可以作为备份、支持报告操作或者作为一个冷备。这种成员被分为以下几种:
三、复制设置注意事项、应用和发展行为
写关注(Write Concerns)
写关注(Write concern)是指每个MongoDB写操作的质量,描述关心应用写操作结果的总量。如果写关注设置为weak或者disabled,则应用会将写操作 发送给MongoDB,不需要等待数据库的响应而继续执行;如果设置为强关注,则写操作会等待MongoDB的写操作确认。MongoDB提供不同的写关 注来适应不同的应用场景。
写关注的类型(按照从弱到强的顺序):
副本集的写关注(Write Concern for Replica Set)
MongoDB内嵌了写关注来确保写操作在副本集中primary的成功。写关注在写操作完成后,使用getLastError命令来获取一个对象,包含错误信息或者是无错误的确认。
默认的写关注只在primary上确认写操作。可以通过getLastError命令的w选项配置副本集中其它成员的写关注。
w选项指定写操作被复制到副本集成员的数目,包括primary。可以通过指定一个数或者majority来确保写操作传播到集合的多数成员。
可以通过getLastError来配置自己的默认副本集行为。使用getLastErrorDefaults设置副本集的配置。下面的命令行是创建一个配置,指定写操作需要在多数成员完成后才能返回。
cfg = rs.conf()
cfg.settings = {}
cfg.settings.getLastErrorDefaults = {w: “majority”}
rs.reconfig(cfg)
可以通过副本集标记(tag)使用getLastErrorDefaults和getLastErrorModes副本集设置来创建一个定制写关注。
举个例子:如果有一个三个成员的副本集,它们有以下标记:
{“disk”:”ssd”}
{“disk”:san, “disk.san”:san}
{“disk”:”spinning”}
然后创建一个定制的getLastErrorModes值:
cfg = rs.conf()
cfg.settings = { getLastErrorModes : { san : { “disk.san” : 1} } }
rs.reconfig(cfg)
通过san使用这个模式指定w选项:
db.runCommand( { getLastError : 1, w : san } )
这个操作在标签disk.san返回之前不会返回。
也可以使用getLastErrorDefaults设置定制写关注:
cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { ssd : 1 }
rs.reconfig(cfg)
读偏好(Read Preference)
读偏好描述了MongoDB客户端如何将读请求路由到副本集的成员。
默认情况下,一个应用会将其读操作导向副本集中的primary。从primary中读可以保证读操作返回的是最新的文档。然后,一个应用如果不需 要完全实时的数据,则可以通过分布一些或全部的读操作到副本集的secondary成员上,从而提高读操作的吞吐量或者降低时延。
MongoDB驱动允许客户端应用对于每个连接、每个collection或者每个操作进行读偏好设置。
读偏好模式同样对通过mongos连接分片簇的客户端有效。
注意:如果一个应用的读操作比例很大,则从secondary成员分布式读可以提高吞吐量。
读偏好模式:
所有的读操作只访问当前副本集的primary,为默认模式。如果primary不可用,则读操作会产生一个error或抛出一个异常。
这个模式与标签集模式的读偏好不兼容。
在通常情况下,从副本集的primary上读数据,当primary不可用时,也就是在故障切换的过程中,从副本集的secondary成员上读数据。
当读偏好包含了标签集时,如果primary可用,客户端从primary上读数据,否则从指定标签的secondary成员上读数据。如果没有匹配标签的secondary时,则产生一个error。
读操作只从副本集的secondary成员上读数据。如果没有secondary可用,则产生一个error或者抛出一个异常。
当读偏好包含标签集时,客户端试图找出指定标签集的secondary成员,并将读操作随机的导向其中一个secondary成员。如果没有相匹配的secondary则产生一个error。
在通常情况下,读操作从secondary成员上读数据,但是当副本集中只有一个primary成员时,则从primary读数据。
当读偏好包含标签集时,客户端试图找出指定标签集的secondary成员,并将读操作随机的导向其中一个secondary成员。如果没有相匹配的secondary则产生一个error。
驱动从最近的集合成员中读数据时一个成员选择的过程。该模式不关注成员的类型,不管是primary还是secondary成员。
当读偏好包含标签集时,客户端试图找到指定标签的集合成员并将读操作导向其中任意的一个成员。
自动重试
在MongoDB驱动和副本集中mongod实例之间的链接必须平衡两个问题:
方法如下:
重连操作对于应用本身是透明的。如果连接允许从secondary成员上读数据,在重连后,应用能够相继从不同的secondary收到两个读取结果。依照个别secondary成员的状态,文档能够反映不同时间的数据库状态。
在收到error后,驱动使用指定的读偏好模式选择一个新的成员。如果没有指定的读偏好,则使用primary。
请求联合
从secondary读数据能够反映数据集在不同时间点的状态,因为副本集的secondary成员相对于primary的最新状态都有不同程度的 滞后。为了防止后面的读操作在时间上的跳跃,驱动能在第一个读操作后把应用线程绑定到指定的集合成员上。线程持续的从相同成员上读取,直到一下情况发生:
如果应用线程在primary不可用时,发出一次primaryPreferred模式的查询操作,则线程会一直固定的访问一个secondary 成员,尽管primary恢复后,也不会切回。同样的,如果线程在所有secondary成员都down掉时,发起一次 secondaryPreferred模式的查询,应用线程会一直从primary上进行读取,尽管secondary恢复。
成员选择
客户端通过驱动和分片簇的mongos实例会定期的更新副本集的状态:哪些成员up或down了,哪个成员成为了primary,以及每个mongod实例的延迟。
对于任意针对非primary成员的操作,驱动会:
分片和mongos
在多数的分片簇中,一个副本集提供每一个分片,这里读偏好也是可用的。分片簇中的带有读偏好的读操作与不分片副本集是完全相同的。
与简单的副本集不同的是,在分片簇中,客户端所有与分片的交互都是通过mongos连接到副本集成员上。Mongos负责应用的读偏好,这对应用是透明的。
在支持所有读偏好的分片环境中没有配置更改的需要。所有的mongos保存着他们自己与副本集成员间的连接池。
四、副本集内部组成和行为
Oplog内部组成
在各种异常情况下,更新一个secondary的oplog可能会比预期时间有所延迟。
所有副本集的成员会在集合中向其它所有成员发送心跳(ping)包,并且能够将集合中的其它成员的操作加入本地oplog。
副本集的oplog操作时幂等的。下面的操作时需要幂等的:
读偏好的内部组成
MongoDB使用单一主复制来确保数据库保持一致性。然而,客户端可能修改每个连接的读偏好来分发读操作到从副本集中的secondary成员上。一个以读为主的部署能够通过分发读取到secondary成员上实现更多的查询。但
选举内部组成
选举是副本集选择某个成员成为primary的过程。primary是一个副本集中唯一能够接收写操作的成员。
下面的事件能够引发一次选举:
在选举过程中,所有的成员都有一票,包括隐藏成员、仲裁者和正在恢复的成员。任意mongod能够否决一次选举。在默认的配置中,所有成员都有相同 的机会成为primary。然而可以通过设置优先级来影响选举。在一些结构中,这可能有操作因素来提高一个成员成为primary的可能性。例如,一个在 远程数据中心的成员不应该成为primary。
任意成员都能否决一次选举,尽管这个成员是一个非投票成员。
一个成员在下列情况下会否决一次选举:
第一个接收到集合中多数选票的成员将成为primary,只到下次选举。了解下面的条件和可能的情况:
同步
为了能够跟上副本集的最近状态,设置成员从其它成员同步或者复制oplog记录。成员同步数据在两个不同的点:
例子:
在MongoDB2.2以后,secondary成员还可以进行以下附加的同步行为:
如果用于来oplog记录的连接有30秒时间没有反应,则Secondary成员停止从这个成员进行同步。如果一个连接超时,则该成员会重新选择一个新的成员进行同步。
多线程复制
MongoDB的批量写操作使用的多线程方式。复制过程将一组有大量并发操作的线程中每个批处理分开。
尽管多线程可能会使操作失序,客户端从secondary成员读取数据不会收到返回的documents,这反映了一个不会在primary存在的中间状态。为了确保一致性,MongoDB会在处理批操作时阻塞所有的读操作。
为了改进操作应用的性能,MongoDB获取所有保存数据的内存页和批处理将要影响的操作的索引。预取阶段将MongoDB持有写操作锁的时间缩到最短。
预取索引以提高复制的吞吐量
默认情况下,secondary在通常会预取与操作影响的document的索引以此提高复制的吞吐量。可以限制只针对于_id域使用预取功能,或者完全关闭该功能。
五、主从复制
从1.6版本起,副本集方式就代替了主从复制。所有新的产品架构都使用了副本集而不是主备复制。
副本集提供了主从关系的功能超集,能够使产品更健壮。主从复制优先复制,使其有大量的非主节点,且只为一个单独的数据库进行复制操作。然而主从复制提供少量冗余,且不能自动故障切换。
故障切换到从节点(提升)
永久的就从不可用或毁坏的主节点A切换到从节点B上:
转换主从关系
如果有一个主A和一个从B,想要转换它们的关系,则遵循以下过程。这个过程假设A是健康的、最新的和可用的。
如果A不是健康的,但硬件是正常的,则跳过①和②,并在第⑧步将所有的A文件替换为B文件。
如果A不是健康的,且硬件也不正常,则使用一个新机器代替A。
转换主从部署:
① 使用fsync命令停止A上的写操作
② 确保B跟上了A的状态
③ 关闭B
④ 备份并移除所有B节点上以local开头的dbpath下的数据文件
⑤ 以master选项重新启动B
⑥ 在B上进行一个写操作,这样可以使oplog提供一个新的同步时间点
⑦ 关闭B,B目前有新的以local开头的数据集文件
⑧ 关闭A,替换A上以local开头的dbpath路径下的所有文件为B上以local开头的dbpath路径下的文件拷贝。确认在拷贝B的本地文件时要进行压缩,因为这些文件有可能很大。
⑨ 以master选项启动B
⑩ 以slave选项启动A,但是包含fastsync
恢复时过时太多则要重新同步
从节点异步从主节点上接收写操作,从主节点的oplog上拉取数据。Oplog的长度有限,如果从节点落后太多,重新同步是非常必要的。重新同步从节点,则连接上从节点的mongod,并执行resync命令:
use admin
db.runCommand( { resync : 1 } )
从节点链
从节点不能被穿成链,它们必须与主节点直接相连。如果一个从节点试图作为另一个从节点的从节点,你将在mongod中看到提示。
本文来自:http://www.cnblogs.com/geekma/archive/2013/05/09/3068988.html
标签:基本 高可用性 报告 多线程 成员 而不是 部署 cells 上进
原文地址:http://www.cnblogs.com/pauline/p/7109752.html