Replica Sets系列文章之:更新配置

MongoDB核心开发工程师 Kristina Chodorow(@kchodorow) 最近在她的博客上表示,她会发表一系列关于MongoDB Replica Sets 相关的文章,向大家详细的进行一次 Replica Sets 的知识培训。其系列文章内容包括下面一些章节:

本文主要对Replica Sets运行过程中的配置更新操作的内部实现机制进行了讲解。

预备知识

首先我们需要明确reconfig的一个原则,那就是保证在reconfig后让整个Replica Sets不会进入一种不可收拾的状态(比如所有节点都变成arbiter)。所以reconfig的时候,会先对新的配置条件进行检查,确实在此条件下能够选举出一个新的primary才行。具体的做法就是与每个节点通信,获取到其选举的投票权重,保证能连接上的机器中,包含投票票数的大多数。

其次,我们需要保证在上面运行reconfig命令的这个节点有成为primary的可能,实际上就是要保证它的priority要大于0。这也是为了保证新的配置能够选举出一个正常的primary节点。

除了这两点,reconfig过程中还会确认新配置的版本号,Replica Sets的名字等等。

局部更新与全量更新

在新的配置经过上面的条件检验通过后,MongoDB会判断目前的更新是增量式的局部更新还是对整个配置进行更新。其实这两个也很好区分,添加一个新节点进来是增量式更新,其它的都会对配置进行整体更新。这两种更新方法内部实现也不相同。

增量更新的方式,只需要新开一个线程进行与新节点的心跳检测就行了。

而全量更新的方式会麻烦一些,它会先将所有当前的状态清除掉,其具体做法就是,primary会关闭所有的心跳检测线程,再对各个新的节点建立新的心跳检测线程,然后用新的配置替换掉老的配置,再然后新的primary会被选举产生。当然,如果原来就有一个primary,那么它通常还继续担任primary的角色。

对于配置更新,我们在大多数情况下都采用了全量的配置更新方式。可能你会觉得,像简单地把一个节点的priority从0改成1这样的修改,直接在原来的配置上改一个字段就行了,但是实际上可能这一小改动可能引发很多后续的问题,很多难以预测的边缘事件可能发生。所以MongoDB索性采用更安全的全量更新方式,让这个操作在复杂的环境下也能安全完成。

新配置的传递

Replica Sets的配置和节点的数据不一样,即使你配置了节点数据是延迟同步的,配置的更新也会马上完成。因为配置更新是通过节点间的心跳检测来做的。不受同步线程的控制。

下面我们通过几个形象的图来演示一下在变更配置后,新的配置是如何在节点间传播的吧。

首先,假设我们有两个节点,A和B,当前的Replica Sets版本号是6

然后我们在A节点上进行reconfig的操作,指定新的配置文件,并且新的配置文件版本号为7

B在对的心跳检测包中会包含自己的配置版本号,这时候B会发给A消息说其版本号为6

当A收到这个消息后,它发现自己当前的版本号已经比B要高了,所以它会将自己当前的配置发送给B节点

当B收到这个消息后,它会对A发过来的新配置进行相同的检验,然后按配置进行相应的操作

强制更新

虽然在reconfig中,会进行各种检验,以保证reconfig后整个系统不会进入无primary的情况。但是总有一些情况,会导致一个Replica Sets中没有primary。所以在2.0版本中,MongoDB提供了 force:true 选项,以强制在无法与大多数节点取得联系的情况下执行reconfig操作。注意,这里的强制只是强制在无法与大多数节点通信时也能进行配置更新,但并不是说会忽略掉前面提到的对配置正确性的检验。

为什么我的配置版本号会变成 6,203,493?

在通过上面的 force:true 选项重新更新配置后,你可能会发现你的配置版本号变得特别大,比如像 6,203,493 这样的大数。这是什么原因呢。这是由于我们在强制更新配置后,会用一个随机数设置配置版本号。因为如果不这样,可能会引发一些问题。

比如我们一个Replica Sets因为网络原因分裂成了两部分(各部分都存在一些节点,各自部分的节点间能互通互联)。这时候两个部分都会认为对方那些节点是故障了,可能我们会分别在两部分都进行强制reconfig操作,如果我们原本的版本号是7,那么两边在reconfig后,如果版本号只是简单的加1,那么会得到两个不同的配置,但是版本号都是8。在网络恢复后,两边的节点会发现大家的版本号都是8,没有什么问题。但是实际上是,两边的节点配置是不同的,而且集群中有两个primary。所以这里会采用一个随机数来作为强制reconfig后的版本号,主要就是为了避免这样的问题。比如保证不会出现两个primary。

另外,由于删除节点可能有很多可能性,删除一个节点最安全的方式是先shutdown,然后再remove掉。而10gen的同学也正在努力对这方面进行改进,有望在2.2版本得到增强。

来源:www.snailinaturtleneck.com

anyShare赠人玫瑰,手有余香,分享知识,德艺双馨!
          

无觅相关文章插件,快速提升流量

分类 MongoDB · tag ,