0

情况:我在两台计算机上有一个 MongoDB 复制集。

  • 一台计算机是拥有主节点和仲裁器的服务器。此服务器是实时服务器,并且始终处于开启状态。复制中使用的本地 IP 是192.168.0.4.
  • 第二个是辅助节点所在的 PC,每天运行几个小时。复制中使用的本地 IP 是192.168.0.5.

我的期望:我希望实时服务器成为我的应用程序数据交互的主要点,无论 PC 的状态如何(是否可达,因为 PC 是辅助的),所以我想确保服务器的节点始终是主要的。

以下是 的结果rs.config()

liveSet:PRIMARY> rs.config()
{
    "_id" : "liveSet",
    "version" : 2,
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.0.4:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 10,
            "tags" : {

            },
            "slaveDelay" : 0,
            "votes" : 1
        },
        {
            "_id" : 1,
            "host" : "192.168.0.5:5051",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {

            },
            "slaveDelay" : 0,
            "votes" : 1
        },
        {
            "_id" : 2,
            "host" : "192.168.0.4:5052",
            "arbiterOnly" : true,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {

            },
            "slaveDelay" : 0,
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatTimeoutSecs" : 10,
        "getLastErrorModes" : {

        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        }
    }
}

如果这很重要,我还将存储引擎设置为 WiredTiger。

我实际得到的是什么,以及问题:当我关闭 PC 或终止其 mongod 进程时,服务器上的节点将成为次要节点。

以下是我在连接到主节点的 shell 时杀死 PC 的 mongod 进程时服务器的输出:

liveSet:PRIMARY>
2015-11-29T10:46:29.471+0430 I NETWORK  Socket recv() errno:10053 An established connection was aborted by the software in your host machine. 127.0.0.1:27017
2015-11-29T10:46:29.473+0430 I NETWORK  SocketException: remote: 127.0.0.1:27017 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
2015-11-29T10:46:29.475+0430 I NETWORK  DBClientCursor::init call() failed
2015-11-29T10:46:29.479+0430 I NETWORK  trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2015-11-29T10:46:29.481+0430 I NETWORK  reconnect 127.0.0.1:27017 (127.0.0.1) ok
liveSet:SECONDARY>


我有两个疑问:

  1. 考虑到MongoDB 文档的这一部分

副本集使用选举来确定哪个集成员将成为主要成员。选举在启动副本集之后发生,并且在主节点变得不可用的任何时候发生。

选举发生在主节点不可用时(或在启动时,但这部分与我们的情况无关),但主节点始终可用,所以为什么会发生选举。

  1. 考虑到同一文档的这一部分:

如果大部分副本集不可访问或不可用,则副本集无法接受写入,并且所有剩余成员都变为只读。

考虑到“成员变为只读”部分,我有两个节点向上和一个向下,所以这也不应该影响我们的复制。

现在我的问题是:当 PC 上的节点无法访问时,如何将服务器上的节点保持为主节点?

更新: 这是rs.status().

感谢 Wan Bachtiar,现在这使得行为变得明显,因为无法访问仲裁器。

liveSet:PRIMARY> rs.status()
{
    "set" : "liveSet",
    "date" : ISODate("2015-11-30T04:33:03.864Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.0.4:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1807553,
            "optime" : Timestamp(1448796026, 1),
            "optimeDate" : ISODate("2015-11-29T11:20:26Z"),
            "electionTime" : Timestamp(1448857488, 1),
            "electionDate" : ISODate("2015-11-30T04:24:48Z"),
            "configVersion" : 2,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "192.168.0.5:5051",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 496,
            "optime" : Timestamp(1448796026, 1),
            "optimeDate" : ISODate("2015-11-29T11:20:26Z"),
            "lastHeartbeat" : ISODate("2015-11-30T04:33:03.708Z"),
            "lastHeartbeatRecv" : ISODate("2015-11-30T04:33:02.451Z"),
            "pingMs" : 1,
            "configVersion" : 2
        },
        {
            "_id" : 2,
            "name" : "192.168.0.4:5052",
            "health" : 0,
            "state" : 8,
            "stateStr" : "(not reachable/healthy)",
            "uptime" : 0,
            "lastHeartbeat" : ISODate("2015-11-30T04:33:00.008Z"),
            "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
            "configVersion" : -1
        }
    ],
    "ok" : 1
}
liveSet:PRIMARY>
4

1 回答 1

2

如文档中所述,如果大部分副本集不可访问或不可用,则副本集无法接受写入,并且所有剩余成员都变为只读。

在这种情况下,如果无法访问仲裁器和辅助节点,则主节点必须下台。rs.status()应该能够确定副本成员的健康状况。

您还应该注意的一件事是主oplog 大小。oplog 的大小决定了一个副本集成员可以停机多长时间,并且在它重新上线时仍然能够赶上。oplog 的大小越大,您处理成员宕机的时间就越长,因为 oplog 可以容纳更多的操作。如果它确实落后太多,您必须通过删除其数据文件并执行初始同步来重新同步成员。

有关详细信息,请参阅检查 Oplog 的大小

问候,

万。

于 2015-11-30T11:19:00.683 回答