MongoDB写入关注为1时主节点回滚原因及选举相关疑问
这个问题问到点子上了,刚好是MongoDB副本集一致性模型里的关键细节,我来给你拆解清楚:
咱们得先明确MongoDB副本集的核心规则:整个副本集只能有一个“数据权威”——也就是当前的主节点,所有节点最终必须和这个权威保持数据一致。
当原主节点在没把写入同步到多数从节点前就宕机,这些写入只存在于原主自己的磁盘上,没有得到多数节点的确认。等原主恢复时,副本集里已经有了新的主节点(选举产生的),新主已经接收了新的写入,它的oplog已经往前推进了。这时候原主的oplog和新主的oplog就出现了分支:新主的oplog是从原主宕机的那个点继续往后走的,而原主的oplog在那个点后面多了一段只有它自己有的写入。
为了维护整个副本集的数据一致性,原主必须放弃这段“孤立”的写入——因为这段数据没有被多数节点认可,也不在当前权威(新主)的oplog里。所以它会执行回滚,把自己的数据回退到和新主一致的位置,然后再从新主同步后续的所有操作。
没错,选举是触发这个流程的直接原因:
- 原主宕机后,多数节点会判定它不可用,立刻触发选举,选出新的主节点,新主就成为了新的数据权威。
- 如果原主只是短暂失联,多数节点还没来得及选出新主,那原主恢复后依然是主节点,从节点会继续从它这里同步未完成的数据,自然不会有回滚。
这种情况其实不会发生。选举的前提是原主被多数节点标记为不可用,当原主恢复时,如果已经有新主产生,它想重新当选的话,必须满足两个条件:一是它的数据和当前主节点一致,二是获得多数节点的投票。但它现在有一段孤立的写入,其他节点会认为它的数据和权威不一致,根本不会投它的票,所以它只能以从节点的身份加入副本集,然后执行回滚。
只有一种例外:原主失联的时间极短,多数节点还没完成选举流程,这时候原主恢复,会重新接管主节点的身份,这时候没有新主,它的数据还是权威,也就不需要回滚。
你提到的w: majority写入关注之所以能避免回滚,核心原因是:当你用这个参数时,MongoDB会等写入操作被多数节点确认后,才给客户端返回“写入成功”。这样一来,即使原主宕机,这些写入已经存在于多数节点上,新主的oplog里也会有这些数据,原主恢复时就不会有孤立的写入,自然不需要回滚。
内容的提问来源于stack exchange,提问作者user12582392

