目录
一、副本集构成
二、问题发生与解决
三、问题分析
1. 为何触发重新选举
2. 主何时被认为已失效
3. 选主过程
4. 关于候选节点(Candidate Node)
(1)候选节点的定义
(2)候选节点的产生条件
(3)候选节点的行为
(4)候选节点与主节点、从节点的关系
(5)候选节点的作用与意义
5. 平票怎么办
6. 优先级的作用
7. 结论
一、副本集构成
一个线上 MongoDB 集群,版本是 3.0.15,副本集由以下五个节点(一主四从)构成:
主:172.30.4.28:30001; votes=1; priority=10;
从:172.30.4.42:30001; votes=1; priority=1;
从:172.20.1.40:30001; votes=1; priority=5;
从:172.20.1.41:30001; votes=1; priority=1;
从:172.20.1.42:30001; votes=1; priority=1;
其中 30 网段有一主一从两个节点,20 网段有三个从节点。应用程序直连的 172.30.4.28。
二、问题发生与解决
20 与 30 两个网段之间断网,之后 30 网段的两个节点 172.30.4.28 与 172.30.4.42 都变为从,重启后依然,应用程序无法正常向 MongoDB 中写入数据。解决方法是在原来的主节点上执行如下操作:
# 切换到管理库
use admin
# 获取当前副本集配置
cfg=rs.conf()
# 重新配置副本集,只配置 30 网段的两个节点,并取消其中一个节点的投票权
cfg.members = [cfg.members[0], cfg.members[1]]
[
{
"_id" : 2,
"host" : "172.30.4.42:30001",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 0
},
{
"_id" : 3,
"host" : "172.30.4.28:30001",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 10,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
}
]
# 强制重新配置副本集
rs.reconfig(cfg, {force :true })
完成后副本集一主一从,应用程序访问正常,问题解决。
三、问题分析
1. 为何触发重新选举
MongoDB 触发重新选举(re-election)一个新的 primary 节点通常发生在以下几种情况:
- 当前的 primary 节点因某些原因宕机或无法与集群中的大多数节点通信时。
- 当前的 primary 节点可能会因为网络分区或其它一些情况而被集群认为已经失效,此时它会自动从集群中移除。
本例中,primary 节点没有宕机,但同时与三个从节点失联后被认为已经失效,状态由 PRIMARY 变为了 SECONDARY, 从而触发了重新选举。那么 primary 节点为什么被认为是已经失效呢?
2. 主何时被认为已失效
在 MongoDB 中,当一个副本集的主节点(primary)失效时,副本集会开始一个选举过程来选出新的主节点。主节点被认为已失效的时间点通常是它无法与副本集中的大多数节点通信,且不能持续一段时间的“心跳”检查。
具体的失效判定条件取决于副本集的配置和操作系统时钟的准确性。一般来说,如果主节点在一段时间内(默认是10秒)不能与副本集中大多数的节点进行通信,那么这个节点会被认为已经失效。简单说就是与大多数节点失联10秒即属失效。
在选举开始之后,副本集中的其他节点会尝试选出新的主节点。一旦新的主节点被选出,副本集会开始接受客户端的写操作。注意,这个过程可能会导致短暂的服务中断,停服时间取决于副本集的大小和网络延迟。
下一个问题是怎么选主的呢?
3. 选主过程
MongoDB 的选主过程(也称为选举)是集群中的节点决定谁将成为主节点(primary)的过程。这个过程是自动的,通常在主节点失效时触发。MongoDB 使用复杂的投票协议来选主,这意味着在一个集群中,每个节点都会向其他节点投票来表明它选举的主节点,获得多数票的节点成为主节点。
以下是 MongoDB 选主过程的简化步骤:
- 每个节点开始于一个状态,通常是 STARTUP 或 SECONDARY。
- 当集群中的节点检测到主节点失效时,它们进入 RECOVERING 状态并开始选主过程。
- 每个节点向其他节点发送一个投票,包括了自己的服务器 ID 和任期号(term)。
- 其他节点接收投票并决定是否接受,基于它们已经投给的节点和它们对候选节点的看法。
- 当一个节点获得大多数节点的投票,它成为主节点,并将其余节点置为次节点或辅助节点。
注意,MongoDB 使用的投票协议保证了在任何给定的任期号(term)内只有一个主节点。如果在同一任期号内出现多个节点获得相同数量的投票,则选举过程会重新开始,并增加任期号。
MongoDB 的选主过程是自动的,通常不需要人工干预。那么下一个问题是什么没有选出新的主节点呢?
4. 关于候选节点(Candidate Node)
在 MongoDB 中,候选节点(Candidate Node)是副本集(ReplicaSet)选举过程中的一个重要角色。以下是对 MongoDB 候选节点的详细解释。
(1)候选节点的定义
候选节点是在 MongoDB 副本集选举过程中,由从节点(Secondary Node)转变而来的一个临时状态。当副本集中的主节点(Primary Node)不可用时(例如,宕机、失去联系或主动放弃主节点角色),剩余的从节点将触发选举过程,其中一个或多个从节点可能会转变为候选节点,以竞选成为新的主节点。
(2)候选节点的产生条件
一个副本节点成为候选节点,需要满足以下条件和配置:
- 节点优先级:要使副本节点成为候选节点,需要将其优先级设置为大于 0 的值。通常,优先级较高的节点更有可能成为候选节点。
- 数据一致性:在选举过程中,只有拥有最新数据的节点才有可能被其它节点投票支持成为主节点。因此,副本节点需要保持与主节点的数据一致性,并随时准备在选举过程中提供最新的数据副本。
- 网络连接:副本节点需要与副本集中的其它节点保持网络连接,以便在选举过程中接收和发送心跳信号和选举请求。如果副本节点与大多数节点失去连接,它将无法参与选举或被其它节点选举为主节点。
(3)候选节点的行为
- 发起选举请求:一旦成为候选节点,它会向副本集中的其它节点发送选举请求,请求它们投票支持自己成为新的主节点。选举请求中通常包含候选节点的任期(Term)信息和日志索引(Log Index)等关键信息。
- 等待投票:候选节点会等待其它节点的响应。这些响应可以是支持票(即投票给候选节点),也可以是反对票(即不投票给候选节点)。
- 处理投票结果:如果候选节点在选举超时之前获得了超过半数节点的支持票,它将成为新的主节点,并开始处理写操作和协调读取操作。如果未获得足够的支持票,则选举失败,候选节点将重置选举超时计时器,并可能再次尝试发起选举。
(4)候选节点与主节点、从节点的关系
- 与主节点的关系:在选举过程中,候选节点是竞选成为新主节点的节点。一旦成功当选,候选节点将转变为新的主节点,并承担主节点的职责。如果选举失败,则候选节点将重新变为从节点,等待下一次选举机会。
- 与从节点的关系:在正常情况下,候选节点是从节点的一个子集。当主节点不可用时,部分或全部从节点可能会转变为候选节点以参与选举。然而,在选举过程中,只有获得足够支持票的候选节点才能成为新的主节点,而其它候选节点和未参与选举的从节点将继续作为从节点存在。
(5)候选节点的作用与意义
候选节点的存在是 MongoDB 副本集选举机制的重要组成部分。它确保了当主节点不可用时,副本集能够迅速且有效地选举出一个新的主节点来继续处理写操作和协调读取操作。这有助于保持数据的一致性和系统的高可用性。同时,候选节点的竞争机制也有助于防止单点故障和数据丢失的风险。
综上所述,MongoDB 的候选节点是副本集选举过程中的一个关键角色。它通过与从节点和主节点的交互以及自身的行为来确保选举的顺利进行和系统的稳定运行。
在本例中,两个节点虽然优先级不同,但都满足成为候选节点的条件,都成为了候选节点,并且都给对方投了一票,因此出现了平票而无主的情况。
5. 平票怎么办
MongoDB 的选举过程遵循一定的规则和条件,包括节点的状态、数据的更新情况、选举权重以及节点的优先级等。本例中,30 网段只有两个节点,它们各有一票,都没有获得多数票,所以状态都为 SECONDARY,没有选出新的主节点。
但是,这两个节点的优先级分别是 10 和 1,优先级高的没有被选为主。
在选举过程中,如果多个节点获得了相同数量的投票,MongoDB 的选举机制并不会简单地根据节点的优先级来选择 primary。这是因为选举机制的设计目标是确保数据的一致性和服务的连续性,而不仅仅是基于节点的优先级。
具体来说,当多个节点平票时,MongoDB 会考虑其他因素来打破平局,例如节点的数据更新情况(通过操作日志 oplog 来检查)和节点的稳定性等。如果两个节点的数据版本相同且优先级也相同,那么选举过程可能会陷入僵局,直到某个节点因为数据更新或其他因素而获得更多支持。
那优先级的作用又是什么呢(尤其实在平票的情况下)?
6. 优先级的作用
在副本集中,每个成员节点都有一个与之关联的优先级,这个优先级决定了节点在选举过程中成为主节点(primary)的权重。优先级越高,节点在选举中获胜的可能性就越大(其实就是越可能被投票)。
虽然优先级在选举过程中是一个重要因素,但它并不是决定性的,起决定性作用的还是节点所获得的票数。如果选举过程中出现平票,优先级高的节点并不会被自动选为 primary。
此外,需要注意的是,MongoDB 的副本集设计中通常建议节点数为奇数(更准确地说是一个网络分区中的节点数为奇数),这是为了确保在投票过程中能够避免出现平票情况。因为奇数个节点可以确保在大多数情况下都能选出一个明确的 primary 节点。注意,本例和通常所说的“脑裂”情况不一样,通常所说的“脑裂”是指在一个集群中出现多主,而本例是无主。
7. 结论
综上所述,MongoDB 选举 primary 的决定因素是票数,平票情况下优先级大的节点也不会被选,此时 MongoDB 会考虑其他因素来打破平局,以选举出一个合适的 primary 节点来继续提供服务。但是这钟机制并不能保证选举出主节点,本例就是。
因此,在配置 MongoDB 副本集时,除了设置节点的优先级外,还需要考虑其他因素,如节点的数据更新情况、稳定性以及副本集的整体架构等,以确保选举过程的顺利进行。