个人博客
整理mongodb文档:副本集成员可以为偶数
想了下,仲裁节点还是不想直接说太多,怕有的同学想太多,且本身副本集就偏向运维的,新手基本也没什么权限操作,就不多废话了。
文章概叙
文章从MongoDB是否可以用偶数节点切入,讲解关于仲裁节点以及节点选举。
今天所要讲解的是关于ReplSet成员必须为奇数,今天跟一个朋友讨论时候,他提到了副本集的成员不可以为偶数的观点,我百度了下,也有不少的文章这么提及,但没有说到为什么,由于试错的成本也不高,所以就直接做一个DEMO演示下,分别设置四个节点到三个节点再到两个节点的情况下,主节点出问题的情况下,是否会导致所有的副节点无法选举出主节点。
首先,先来一个四个节点的测试
const config =
{
_id: 'replSetTest60000',
members:
[
{ _id: 0, host: '127.0.0.1:60001' },
{ _id: 1, host: '127.0.0.1:60002' },
{ _id: 2, host: '127.0.0.1:60003' },
{ _id: 3, host: '127.0.0.1:60004' },
]
}
rs.reconfig(config)
接着,停止60001节点,使其发起主节点的选举,可以看到,60002节点已经被选举为了主节点
四节点下是可以正常选举的,此时,再重新设置我们的副本集,模拟下三节点下的选举。
const config =
{
_id: 'replSetTest60000',
members:
[
{ _id: 0, host: '127.0.0.1:60001' },
{ _id: 1, host: '127.0.0.1:60002' },
{ _id: 1, host: '127.0.0.1:60003' }
]
}
rs.reconfig(config)
在使用rs.reconfig 指令重新设置下我们的副本集后,废弃掉60004的服务,记得重新启动60001的服务。
因为当前的主节点是60002节点,所以我们停止掉60002节点的服务,再去查看60001是否被选举为了主节点
依旧可以确定,在三个节点的情况下,当出现选举的时候,不会导致所有的节点都是Secondary。
最后的测试是只有两个节点的,虽然各位都知道副本集不允许只有两个节点存在,但吃饱了没事干,还是测试下。
当前保留了60001节点以及60002节点进行测试,在更新了副本集的配置之后,停用了60003以及60004的服务。
接着停止60001的服务
可以看到,60001的节点停止之后,主节点消失了,而60002节点也没有了转正的机会。
所以,我们可以断定了节点数只能不能为两个,但是没有不能为偶数的限制
仲裁节点
为了解决上文提到的两个节点的问题,便有了仲裁节点的接入,首先了解下关于仲裁节点的概念
在某些情况下(例如有一个主节点和一个从节点,但由于成本约束无法添加另一个从节点),你可以在副本集中添加一个仲裁节点。仲裁节点没有数据集的副本,并且不能成为主节点。然而,仲裁节点可以参与主节点选举。一个仲裁节点只有 1 票选举权。
简单来说,仲裁节点不能保存数据,但是发起投票的时候,他作为一个仲裁者的身份,能决定谁成为主节点。
接着,添加一个仲裁节点到我们的项目中,正常情况下,仲裁节点是要第三方机子,防止主节点跟仲裁节点一起停了。
rs.addArb("127.0.0.1:27019")
在某些场景下, 一个副本集中的两个节点可能会认为它们是主节点,但至多,他们中的一个将能够完成写关心级别为[{ w: “majority” }]的写操作。可以完成 [{ w: “majority” }]写的节点是当前主节点,而另一个节点是原先的主节点,通常是由于网络分区导致它还没有意识到自己的降级。
当这种情况发生时,连接到原先主节点的客户端尽管已经请求了读偏好Primary,但可能还会观察到过时的数据,并且对原先主节点新写的操作最终将回滚掉。
网络分区只在分布式集群中,节点之间由于网络不通,导致集群中节点形成不同的子集,子集中节点之间网络互通,而子集与子集之间网络不通。
注意点
副本集的仲裁节点,不需要了解很多,毕竟项目上线之后,你不用对他做啥操作,建议了解下内容即可,副本集也一样,很多时候你没权操作到,但是很多面试人家会问到相关的知识点。