MongoDB技术博客翻译系列之--- Replica Set 选举

更多关于MongoDB的技术分享请关注我的公众号:mongodb_side

原文地址:

 

http://www.snailinaturtleneck.com/blog/2012/01/04/replica-set-internals-bootcamp-part-i-elections/

根据前MongoDB工程师Kristina Chodorow博文翻译

翻译 shingo[email protected]


 

心跳

假设我们有一个由3个节点组成的复制集,分别是X,Y,Z。每隔2秒钟,他们各自会给复制集中的其它成员发送一个心跳请求。咱们说话的功夫,X已经将心跳请求发送给YZ了,YZ将他们当前的状态信息响应给X,这些信息包括:节点当前所扮演的角色(主、从或观察者)、节点是否适合成为主节点,当前时间等等。

 

X收到这些信息后会更新它所维护的一份复制集信息:节点的增加减少、角色状态改变、本次心跳请求花去的时间。

 

如果X维护的信息发生改变,X需要检查几件事情:如果X是主节点,并且复制集中是有节点当掉了(译者注:当掉是相对的,也可能是X 因为网络问题连接不上其它节点),X 需要确认是否它仍然能够连接上复制集中大多数的节点。不然的话,X 会把自己降级为子节点。

 

降级

关于X降级需要注意的是:在Mongodb 中,写操作默认是非安全的(译者注:具体请见getLastError章节)。因此,如果客户端对主节点做非安全写操作,而主节点又自降为子节点,客户端不会意识到它已经不再是主节点了,会持续发送写操作给它。这个“曾经是主节点现在是子节点”的家伙会说,“我只是一个子节点,不能进行写操作!” 但是由于是非安全写,客户端获取不到响应,所以客户端不知道发生了什么。

 

从技术的角度,我们可能会说:“如果他们注意一点的话应该使用安全写啊”,但这种话看上去太不地道了,不能对客户端的写策略有额外要求。因此,现在的处理方式是,当一个主节点降级后,它会关闭掉所有与客户端的连接,这样的话客户端会收到一个socket error 信息。现在所有客户端开发包在收到error 信息后都会重新检查复制集中哪个节点是主节点。他们能够找到新的主节点,子节点不会再有写入。

 

选举

好了,再回到心跳上来:如果X是一个子节点,即使它所维护的复制集信息没有发生改变,它偶尔也会检查是否需要推选自己了。首先,X会做一个合理性检查:其它节点是否认为X是主节点?X 是否认为自己已经是主节点了?X是不是没有资格进行选举?如果这几个问题有任何一个不满足的话,X将会继续它原来的工作。

 

如果看上去似乎复制集需要一个新的主节点了,X会执行它选举的第一步:它会发送一条消息给YZ告诉他们:我正在考虑竞选主节点,关于这件事你们能给我什么建议么?

 

YZ收到这条消息后,马上快速的检查当前复制集的状况,是否他们自己已经被认为是主节点了?他们是否拥有比X更多的最新数据?他们是否知道有比X拥有更多数据的节点?他们会执行一大串的合理性检查,如果一切看上去都能令他们满意的话,他们会回复给X“你继续,我没意见。如果他们找到一个X不能参加竞选的原因,会回复:停止竞选!

 

如果X 收到任何停止竞选!的消息,它会放弃选举然后做为一个子节点重新回到复制集中。

 

竞选的第二个阶段,X会发出第二条消息,大致意思是我现在正式宣布参选。这时,YZ会做最后的检查:之前有效的那些条件现在仍然站得住脚么?如果是的话,他们会允X 获取他们的选举锁,并且投一票。选举锁会阻止他们在30 秒内投票给其它候选节点。

 

如果在第二次检查中发现有不能满足条件的(非常少见,至少在2.0 版本是这样),他们会投一个否决票。如果有任何人投了否决票,那么X 的这次竞选就算失败了。

 

 

 

 

假设Y 投了赞成票给X,而Z 投了否决票。在这种情况下,Y 选举锁X 拿着,它在30 秒内不再有投票的权利。这意味着,如果Z 想竞选主节点的话,它只需要获得X 的投票。只要Z 只要是一个符合条件的候选者的话,X 应该会把票投给Z 的:复制集中的成员都不像是怀有怨恨的。(Y 除外,它还得静默30 秒呢)

你可能感兴趣的:(mongodb,数据库,NoSQL)