0

新人,学习副本集自动选举时,有诸多疑虑又看不懂源码,做此思考,希望各位大哥看看我想得对不对,先谢谢各位。

官方文档中出现了投票节点(Voting Members)的概念,我没看到定义,思考后认为有两种可能:

猜测一:members[n].votes 被配置为 1 的就是投票节点

猜测二:members[n].votes 被配置为 1 且 处于比较良好的几种状态的就是 投票节点

在主节点不可用,获得多数票的副节点成为主节点,那么这个多数是相对于谁计算的?我没看到官方文档中明说,思考后认为有两种可能:

猜测三:总结点数的多数,比如副本集共 N 个节点,选票大于等于(N / 2 + 1)即为多数

猜测四:投票节点的多数,比如副本集共 N 个节点,M 个投票节点,选票大于等于 (M / 2 + 1)即为多数

有两个可以用于分析的事实:

事实一:副本集最多只能有 7 个投票节点,50 个节点,来自官方文档

事实二:具有四个节点的副本集,在两个节点宕机后,剩余两个节点无法选举出主节点,亲测

事实三:副本集可以有超过 7 个节点 votes 值为 1,亲测

由于事实一,猜测三被否决,猜测四胜出。

由于猜测四 和 事实二,猜测二否决。

由于事实一 和 事实三,猜测一否决。

阶段性结论:members[n].votes 被配置为 1 的是潜在投票节点,但只有处于比较良好的几种状态时可能成为投票节点,且任意时刻最多有 7 个可以成为投票节点,获得投票节点多数票的节点成为主节点。投票节点有两层语义,一可以投票,二可以竞选。

发表新评论

经过进一步研究,发现事实三是错的:当时我使用rs.add()向副本集中增加数据节点后,使用 rs.config() 看到有8个节点votes为1,全程未报错,故得出事实三。后来,当我再次尝试添加节点时,MongoDB抛出了错误,大意是目前投票节点有八个,应该是1-7个。
这个错误非常重要,实锤了猜测一是正确的。

至此,结论已经明朗了:
投票节点有两层语义,一是可以投票,二是可以竞选。非投票节点即不可以投票,也不可以竞选。副本集节点不是投票节点,就是非投票节点。

当 votes 设为 0 时,一个节点就是非投票节点。当 votes 设为 1 时,一个节点就是投票节点,不过投票节点必须处于良好的状态才能投票,才是可用的投票节点。

如果副本集共 N 个节点,M个投票节点,O个可用投票节点,那么选票大于等于(M / 2 + 1)为多数票,如果 O 小于(M / 2 + 1)则副本集无法选出主节点,进入只读状态。