mongodb replicaset 模式下,挂了一个节点导致无法写数据

RT, mongodb replicaset 模式下,挂了一个节点导致无法写数据
一共3台机器,一台 arb 节点,两台主从数据节点,类似于下边这个架构

img

正常状态下的,能进行读写,当主节点挂了也能自动将从节点选举为新的主节点,但当主节点挂了之后,只能正常的读取数据,写入数据出现卡死现象(实际应该是连接从节点超时)

挂掉一个节点后的,rs.status()

{
  set: 'mes',
  date: ISODate("2023-03-03T06:45:30.731Z"),
  myState: 1,
  term: Long("12"),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long("2000"),
  majorityVoteCount: 2,
  writeMajorityCount: 2,
  votingMembersCount: 3,
  writableVotingMembersCount: 2,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1677825908, i: 1 }), t: Long("12") },
    lastCommittedWallTime: ISODate("2023-03-03T06:45:08.592Z"),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1677825908, i: 1 }), t: Long("12") },
    appliedOpTime: { ts: Timestamp({ t: 1677825928, i: 1 }), t: Long("12") },
    durableOpTime: { ts: Timestamp({ t: 1677825928, i: 1 }), t: Long("12") },
    lastAppliedWallTime: ISODate("2023-03-03T06:45:28.594Z"),
    lastDurableWallTime: ISODate("2023-03-03T06:45:28.594Z")
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1677825868, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate("2022-12-02T03:22:41.002Z"),
    electionTerm: Long("12"),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1669951337, i: 1 }), t: Long("11") },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1669951337, i: 1 }), t: Long("11") },
    numVotesNeeded: 2,
    priorityAtElection: 1,
    electionTimeoutMillis: Long("10000"),
    numCatchUpOps: Long("0"),
    newTermStartDate: ISODate("2022-12-02T03:22:43.006Z"),
    wMajorityWriteAvailabilityDate: ISODate("2022-12-02T03:24:36.460Z")
  },
  members: [
    {
      _id: 0,
      name: '192.168.0.1:27001',
      health: 0,
      state: 8,
      stateStr: '(not reachable/healthy)',
      uptime: 0,
      // 省略部分时间数据
      pingMs: Long("0"),
      lastHeartbeatMessage: "Couldn't get a connection within the time limit",
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: 5,
      configTerm: 12
    },
    {
      _id: 1,
      name: '192.168.0.2:27001',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 14617618,
      // .. 省略部分时间参数
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1669951361, i: 1 }),
      electionDate: ISODate("2022-12-02T03:22:41.000Z"),
      configVersion: 5,
      configTerm: 12,
      self: true,
      lastHeartbeatMessage: ''
    },
    {
      _id: 2,
      name: '192.168.0.100:27000',
      health: 1,
      state: 7,
      stateStr: 'ARBITER',
      uptime: 14617614,
      lastHeartbeat: ISODate("2023-03-03T06:45:29.579Z"),
      lastHeartbeatRecv: ISODate("2023-03-03T06:45:29.573Z"),
      pingMs: Long("0"),
      lastHeartbeatMessage: '',
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      configVersion: 5,
      configTerm: 12
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1677825928, i: 1 }),
    signature: {
      hash: Binary(Buffer.from("...", "hex"), 0),
      keyId: Long("000")
    }
  },
  operationTime: Timestamp({ t: 1677825928, i: 1 })
}

此时通过以下连接串登录,仍然能正常读取数据

mongodb://user:pwd@192.168.0.1:27001,192.168.0.2:27001/?connect=replicaSet&replicaSet=mes

但是当执行写入数据的时候却出现卡死的现象,Ctrl+C退出后查看,实际数据被写入了

img

img

求各位mongo大师指点下,是哪里出了问题?是不是缺少什么配置?要怎样才能实现,当挂掉一个节点后,另一节点能自动成为主节点且在未恢复挂掉的节点的同时还能继续正常提供读写服务。

引用 皆我百晓生 小程序回复内容作答:
在您描述的情况下,由于主节点挂掉,另一节点成为新的主节点。然而,写入操作卡住的问题可能是由于挂掉的主节点仍被视为活动节点引起的。

您可以尝试以下步骤解决该问题:

  1. 连接到其他正常工作的节点,并使用rs.remove()命令从复制集中删除挂掉的主节点。例如,运行以下命令将节点ID为0的节点从复制集中删除:
rs.remove(0)
  1. 确保复制集中的所有节点都具有相同的rs.config()配置。如果在故障发生之前更改了配置,请确保所有节点上都按照相同的步骤进行了相同的更改。

  2. 验证剩余节点的状态是否正确。运行rs.status()命令,确保剩余节点的状态正确,并且没有任何节点显示为不可用或其他错误状态。

  3. 如果以上步骤不起作用,请尝试重启整个复制集。确保在重启之前先备份数据。

重启操作可以通过按顺序停止每个节点并再次启动它们来完成。

请注意,复制集的行为和可用性取决于多个因素,包括节点的配置和网络环境。如果问题仍然存在,请考虑查看MongoDB的日志文件,以获取更详细的错误信息,并进行故障排除。