MongoDB Replica Set 选举过程

什么是选举?html

选举是副本集选择某个成员成为primary的过程。primary是一个副本集中惟一可以接收写操做的成员。sql

下面的事件可以引起一次选举:安全

  1. 第一次初始化一个副本集
  2. Primary失效。replSetStepDown命令可以使Primary失效,或者当前secondary成员中有合适的选举者且优先级更高。当Primary与集合中的大多数成员失去联系时也会失效,它会关闭全部的客户端链接,以此防止客户端向一个没有primary成员写数据。
  3. 一个secondary成员于primary失去联系。当secondary成员不能与primary创建一个稳定的链接时会发起选举。
  4. 故障切换发生。

在选举过程当中,全部的成员都有一票,包括隐藏成员、仲裁者和正在恢复的成员。任意mongod可以否决一次选举服务器

                副本集角色属性一览表网络

 

成为primarynosql

对客户端可见socket

参与投票spa

延迟同步htm

复制数据对象

Default (Secondary)

Secondary-Only

Hidden

Delayed

Arbiters

Non-Voting

 


心跳检测
假设咱们有三个节点的replica sets:X,Y和Z节点。在replica sets结构中,这三个节点每2秒会各自向其它两个节点发送一个心跳检测请求。好比X节点向Y和Z节点各发送了一个心跳检测请求,在正常状况下,Y、Z会返回一个包含自身信息的回复包,回复包中主要包括了下面一些信息:它们如今是什么角色(primary 仍是 secondary),他们是否可以在必要的时候成为 primary,以及他们当前时钟时间等等。
X节点在收到回复包后,会用这些信息更新本身的一个状态映射表,更新的内容包括:是否有新的节点加入或有老的节点宕掉,这个请求的网络传输时间等等。
而当X节点的映射表发生了变化,那X会进行下面的逻辑判断:若是X是 primary,而另一个节点出现故障,那么它会看本身是否还能和集群中大多数节点进行通讯,若是不能与大多数节点通讯,那么他会把本身从 primary 降级为 secondary。(在replica sets中,primary 必须可以和集群中的大多数节点进行通讯,以避免发生网络断开造成两个或多个节点群各自为政的状况,这样会影响到数据的一致性)

关于降级
在节点从 primary 降级为 secondary 的过程当中,会有一些问题出现。在 MongoDB 中,写操做默认是经过 fire-and-forget 的模式来进行的,也就是说写操做一般不关心是否成功,发完请求后客户端就认为成功了。但若是这时候 primary 进行降级操做,那么客户端并不知道这时候 primary 已经降级成为 secondary 了,客户端可能还会将后续的写操做发送给这个节点。这时候刚刚降级的这个 secondary 能够发送一个包说“我已经不是 primary 了”,可是咱们上面说过了,客户端根本就无视你这个包。因此客户端根本不知道此次写入已经失败了。
对于这个问题,你可能会说”那咱们每次都使用安全写入不就好了“(安全写入意思是说等待服务器返回成功后客户端才认为写成功了),可是很明显,这很是不靠谱。因此咱们的作法是,在一个 primary 降级成为 secondary 后,它会将原来的全部链接关闭。这样客户端在下一次写入的时候就会出现 socket 错误。而客户端在发现这个错误以后,就会从新向集群获取新的 primary 的地址,并将后续的写操做都往新的服务器上写入。

选举
咱们回头再来看心跳监测请求:若是X是一个 secondary,那么X会定时检测是否须要选举本身成为 primary。其检测内容包括:是否集群中有其它节点认为本身是 primary?X节点本身是否已是 primary?X节点本身是否有资格成为 primary?若是这三个问题中的任何一个回答是否认的,那么X节点就不会试图把本身变成primary。(也就是说,只有当X节点是一个可以当 primary 的secondary,而且其它节点都不是primary时,X才会发起选举并选本身为primary)
而当X发现集群如今须要一个primary而且本身又正好能够充当时,它就会发起一轮选举:X节点会向Y、Z节点各发起一个请求包,告知他们”我认为我能够接管primary的角色,大家以为怎么样?“

当Y和Z收到上面的请求包时,他们会进行下面几项检测:集群中是否有一个 primary了?他们本身的数据是否比X节点更新吗?是否有其它节点的数据比X节点更新?若是上面条件有任何一个知足,那么他们都会认为X不够资格成为 primary,他们会发送一个返回包告知X说”中止选举!“。而若是三个条件都不成立,也就是说他们认为目前集群中确实没有 primary,而且X的数据又是最新的,那么他们会发送返回包告知X说”没问题“。
若是X收到”中止选举!“,那么他会立刻中止选举并保持本身为 sencondary 状态。
若是X收到全部其它节点都返回说”没问题“,那么他会进入选举过程的第二阶段。
在第二阶段中,X会向其它节点发送一个包,说”我宣布我已是 primary 了“。这时候,Y和Z节点再进行一些最终的确认:上面的判断过的全部条件是否依然代表X能够作 primary,若是确实如此,那么他们会在本轮 primary 选举中向X出同意票。而且他们投完同意票后,30秒内不会再作其它投票决定。
那么若是最终确认没有经过,他们会投一个反对票,反对X成为 primary,若是有任何反对票产生,那么这一轮选举就失败了。X仍是保持 secondary 的身份。
下面咱们假设一种状况,若是Y给X投了同意票,而Z给X投了反对票。那这时候Y因为投了同意票,它在30秒内不能再进行投票。因此若是这时候Z发起选举想让本身成为 primary,那么Z这时候必需要得到X的同意票。由于这时候Y不能投票,为了获取多数票,Z必须得到X的同意票。


因此投票的规则是这样的:若是没有投反对票,而且同意票的比例过半,那么本轮选举对象就可以成为 primary

 

转载于http://blog.nosqlfan.com/html/3621.html

相关文章
相关标签/搜索